【发布时间】:2016-04-28 05:26:38
【问题描述】:
我试图在给定索引列值的 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...
【问题讨论】:
-
在像
NVL这样的函数调用中包装索引列可以有效地防止Oracle 使用索引。您可以创建一个基于函数的索引,或者消除NVL调用。 -
如果您选择表的 1/1000 行,索引甚至可能没有用;无论如何,全表扫描可能会更快。
-
@MickMnemonic 啊,我没有意识到 NVL 会破坏索引。这是最不幸的。感谢您的信息。
-
查询中使用的空字符串(我的意思是
'')被 Oracle 视为空值。所以像nvl(column_x,'')这样的表达式没有任何意义,因为字面上等同于if column_x is null return null else return column_x。 -
Oracle 不将空字符串视为 NULL 吗?但是为什么你认为你需要
NVL,NULL 总是不同于'1'。此外,巨大的 IN 列表会降低性能(您是否检查过解析/优化它的时间),您最好将值加载到表中然后加入。
标签: java sql oracle optimization query-optimization