[英]Optimize select query on huge tables?
我试图在给定索引列值的Oracle数据库中抓取特定行。 我选择索引列后跟整个行数据以便于处理。 桌子上大约有1.5亿行,我选择大约100到20万行。 我正在使用NVL()替换IN子句中的空值,因为我在JAVA中动态创建这些语句。 IN子句被分成由OR组合在一起的1000个索引块,以避免“列表中的最大表达式数为1000”错误。
您可以想象,此查询需要很长时间才能运行。 有什么我可以做的来优化这个查询,但保持相同的功能? (忽略索引值,因为它们只是一个例子)
select INDEX_COLUMN_A, INDEX_COLUMN_B, INDEX_COLUMN_C, TABLE.* from TABLE
Where (NVL(INDEX_COLUMN_A,''), NVL(INDEX_COLUMN_B,''), NVL(INDEX_COLUMN_C,''))
IN (('1','1','1'), ('2','2','2'), ... ('1000','1000','1000'))
OR (NVL(INDEX_COLUMN_A,''), NVL(INDEX_COLUMN_B,''), NVL(INDEX_COLUMN_C,''))
IN (('1001','1001','1001'), ('1002','1002','1002'), ... ('2000','2000','2000'))
OR...
如果在('1','1','1')
或('2000','2000','2000')
等测试值中不可能遇到null
,则可以安全地避免nvl()
处于条件状态:
select
INDEX_COLUMN_A, INDEX_COLUMN_B, INDEX_COLUMN_C,
TABLE.*
from
TABLE
where
(INDEX_COLUMN_A, INDEX_COLUMN_B, INDEX_COLUMN_C)
in (
('1','1','1'),
('2','2','2'),
...,
('1000','1000','1000')
)
OR
(INDEX_COLUMN_A, INDEX_COLUMN_B, INDEX_COLUMN_C)
in (
('1001','1001','1001'),
('1002','1002','1002'),
...,
('2000','2000','2000')
)
or
...
此外,表达式如a in (x1,x2) or a in (x3,x4)
表示((a=x1 or a=x2) or (a=x3 or a=x4))
。 :在这种情况下托架可以没有后果被省略(a=x1 or a=x2 or a=x3 or a=x4)
可与被缩短in
表达为a in (x1, x2, x3, x4)
因此,初始查询(如果要测试的值中没有空值)与以下内容相同:
select
INDEX_COLUMN_A, INDEX_COLUMN_B, INDEX_COLUMN_C,
TABLE.*
from
TABLE
where
(INDEX_COLUMN_A, INDEX_COLUMN_B, INDEX_COLUMN_C)
in (
('1','1','1'),
('2','2','2'),
...,
('1000','1000','1000')
...,
('1001','1001','1001'),
('1002','1002','1002'),
...,
('2000','2000','2000')
)
PS
a in (x,y,z)
只是由or
((a=x) or (a=y or (a=z))
连接的等式关系集的快捷方式,而null
永远不等于null
,因此表达式为null in (x,y,z)
永远不会返回true
无论x
, y
和z
值如何。所以如果你真的需要处理null
值,那么表达式必须改为nvl(a,'some_never_encountered_value') in (nvl('1', 'some_never_encountered_value'), nvl('2','some_never_encountered_value'),...)
。但是在这种情况下你不能在表上使用简单索引。可以构建功能索引来处理这样的表达式,但是这是一个非常不同的故事。
PPS如果列包含数字,则必须根据数字进行测试:而不是('1','1','1')
您应该使用(1,1,1)
。
使用or
在where
子句中也可以防止使用索引。 您可以替换查询
select *
from table
where <condition1> or <condition2>
同
select *
from table
where <condition1>
union all
select *
from table
where <condition2>
反过来,第二个查询可以产生重复的行(它取决于数据)。 为了防止重复,您可以使用union
而不是union all
,但使用union
也会引发性能问题。 你需要进行一些实验,这种方式在你的情况下是最好的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.