在大型 oracle table 中搜索值列表时能否获得良好的性能?
Can I get good performance when searching a large oracle table for a list of values?
我正在努力提高我正在从事的项目的性能,但发现最大的瓶颈在某个查询中。
select bar from foo where bar in (:bars);
查询的目的只是为了从 foo table 中反弹一堆 bar 的值,以查看哪些 bars 在里面,哪些不在。 foo table 非常大,此查询至少需要 10 分钟,即使输入列表中只有 5 个柱。
现在这是另一个仅适用于一个柱的查询:
select case when exists (select 1 from foo.bar where bar = 'value') then 'Y' else 'N' end from dual;
这 运行 只需几分之一秒,就能为我提供所需的信息。
这两个查询在解释计划上的区别是第一个使用 'fast full scan' 而第二个使用 'skip scan'。如果重要的话,条形列会被编入索引。
问题是,如果我完全可以得到一个 运行 具有第二个查询的性能但允许我像第一个查询一样向它抛出多个条的查询怎么办?这对我来说很重要,因为一次要检查 10k-100k 条柱是很常见的,不仅是一秒钟的分数加起来,而且每个数据库连接都是一个故障点。
编辑:另外,如果重要的话,查询是 运行 in Java,特别是 org.springframework.jdbc.core.JdbcTemplate class。无论是通过 Java 运行 查询还是在 SQL Developer 运行 中进行查询,我都获得了相同的性能指标。
考虑到您对索引和 table 的所有限制..尝试下面的查询是否是一次 activity:如果它像下面这样动态构建为 CTE 并尝试
with cte
as
(select 1 bar from dual
union all
select 2 from dual
union all
select 3 from dual
union all
select 4 from dual
union all
select 5 from dual)
select bar from foo where exists(select bar from cte where cte.bar=foo.bar);
我认为 kanagaraj 的想法是正确的,但查询仍然像以前一样慢,因为那里仍然有一个 "select bar from foo" 触发快速全面扫描。然而,查询的修改版本提供了我正在寻求的性能(当然还有预期的结果)。
with cte as (
select 1, case when exists (select null from foo where bar = 1) then 'Y' else 'N' end from dual
union all
select 2, case when exists (select null from foo where bar = 2) then 'Y' else 'N' end from dual
union all
...
)
select * from cte;
如果有人想出更优雅的东西,我会保留这个问题,但感谢那些热心提供帮助的人。如果没有您的意见,我不会找到可行的解决方案。
我正在努力提高我正在从事的项目的性能,但发现最大的瓶颈在某个查询中。
select bar from foo where bar in (:bars);
查询的目的只是为了从 foo table 中反弹一堆 bar 的值,以查看哪些 bars 在里面,哪些不在。 foo table 非常大,此查询至少需要 10 分钟,即使输入列表中只有 5 个柱。
现在这是另一个仅适用于一个柱的查询:
select case when exists (select 1 from foo.bar where bar = 'value') then 'Y' else 'N' end from dual;
这 运行 只需几分之一秒,就能为我提供所需的信息。
这两个查询在解释计划上的区别是第一个使用 'fast full scan' 而第二个使用 'skip scan'。如果重要的话,条形列会被编入索引。
问题是,如果我完全可以得到一个 运行 具有第二个查询的性能但允许我像第一个查询一样向它抛出多个条的查询怎么办?这对我来说很重要,因为一次要检查 10k-100k 条柱是很常见的,不仅是一秒钟的分数加起来,而且每个数据库连接都是一个故障点。
编辑:另外,如果重要的话,查询是 运行 in Java,特别是 org.springframework.jdbc.core.JdbcTemplate class。无论是通过 Java 运行 查询还是在 SQL Developer 运行 中进行查询,我都获得了相同的性能指标。
考虑到您对索引和 table 的所有限制..尝试下面的查询是否是一次 activity:如果它像下面这样动态构建为 CTE 并尝试
with cte
as
(select 1 bar from dual
union all
select 2 from dual
union all
select 3 from dual
union all
select 4 from dual
union all
select 5 from dual)
select bar from foo where exists(select bar from cte where cte.bar=foo.bar);
我认为 kanagaraj 的想法是正确的,但查询仍然像以前一样慢,因为那里仍然有一个 "select bar from foo" 触发快速全面扫描。然而,查询的修改版本提供了我正在寻求的性能(当然还有预期的结果)。
with cte as (
select 1, case when exists (select null from foo where bar = 1) then 'Y' else 'N' end from dual
union all
select 2, case when exists (select null from foo where bar = 2) then 'Y' else 'N' end from dual
union all
...
)
select * from cte;
如果有人想出更优雅的东西,我会保留这个问题,但感谢那些热心提供帮助的人。如果没有您的意见,我不会找到可行的解决方案。