我可以知道为什么索引不可能加速某些查询的查询处理吗?
May I know why its impossible for an index to speed up query processing for certain queries?
我已尝试解释并显示此查询的执行计划:
解释
的计划
SELECT *
FROM LINEITEM
WHERE l_quantity = 6
OR l_shipMode = 'MAIL';
SELECT * FROM table(dbms_xplan.display);
输出为:
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 98068815
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 287K| 34M| 8802 (1)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| LINEITEM | 287K| 34M| 8802 (1)| 00:00:01 |
------------------------------------------------------------------------------
然后我在 l_quantity
和 l_shipMode
上创建了一个索引:
CREATE INDEX lineItemIdx ON LINEITEM(l_quantity, l_shipMode);
那我再解释一下并展示一下执行计划:
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 98068815
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 287K| 34M| 8802 (1)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| LINEITEM | 287K| 34M| 8802 (1)| 00:00:01 |
------------------------------------------------------------------------------
没有区别。查询现在不应该使用索引吗?
唉,大多数数据库在优化 or
表达式方面做得很差(Oracle 是个例外)。
您可以使用 union all
:
得到您想要的
SELECT li.*
FROM LINEITEM li
WHERE l_quantity = 6
UNION ALL
SELECT li.*
FROM LINEITEM li
WHERE l_shipMode = 'MAIL' AND l_quantity <> 6;
为此,您需要两个 索引:LINEITEM(l_quantity)
和LINEITEM(l_shipMode, l_quantity)
。
在您的查询中,您有两个条件与 OR
子句相结合:
WHERE l_quantity = 6
OR l_shipMode = 'MAIL';
这意味着对于过滤条件的评估,索引
INDEX lineItemIdx ON LINEITEM(l_quantity, l_shipMode);
OR 子句的两个部分中的每一个都无法正常工作..
所以查询需要全扫描,索引没有用。
这种情况下的索引应该只对条件
有用
WHERE l_quantity = 6
或
WHERE l_quantity = 6
AND l_shipMode = 'MAIL';
或者使用两个索引重建基于 UNION
的两个分离查询的查询
我已尝试解释并显示此查询的执行计划:
解释
的计划SELECT *
FROM LINEITEM
WHERE l_quantity = 6
OR l_shipMode = 'MAIL';
SELECT * FROM table(dbms_xplan.display);
输出为:
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 98068815
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 287K| 34M| 8802 (1)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| LINEITEM | 287K| 34M| 8802 (1)| 00:00:01 |
------------------------------------------------------------------------------
然后我在 l_quantity
和 l_shipMode
上创建了一个索引:
CREATE INDEX lineItemIdx ON LINEITEM(l_quantity, l_shipMode);
那我再解释一下并展示一下执行计划:
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 98068815
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 287K| 34M| 8802 (1)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| LINEITEM | 287K| 34M| 8802 (1)| 00:00:01 |
------------------------------------------------------------------------------
没有区别。查询现在不应该使用索引吗?
唉,大多数数据库在优化 or
表达式方面做得很差(Oracle 是个例外)。
您可以使用 union all
:
SELECT li.*
FROM LINEITEM li
WHERE l_quantity = 6
UNION ALL
SELECT li.*
FROM LINEITEM li
WHERE l_shipMode = 'MAIL' AND l_quantity <> 6;
为此,您需要两个 索引:LINEITEM(l_quantity)
和LINEITEM(l_shipMode, l_quantity)
。
在您的查询中,您有两个条件与 OR
子句相结合:
WHERE l_quantity = 6
OR l_shipMode = 'MAIL';
这意味着对于过滤条件的评估,索引
INDEX lineItemIdx ON LINEITEM(l_quantity, l_shipMode);
OR 子句的两个部分中的每一个都无法正常工作..
所以查询需要全扫描,索引没有用。
这种情况下的索引应该只对条件
有用WHERE l_quantity = 6
或
WHERE l_quantity = 6
AND l_shipMode = 'MAIL';
或者使用两个索引重建基于 UNION
的两个分离查询的查询