我使用两种不同的方法来检查数据库字段column_b是否不是NULL.哪个更快,为什么?
第一个查询
SELECT * FROM my_table
WHERE column_b IS NOT NULL;
Run Code Online (Sandbox Code Playgroud)
第二个查询
SELECT * FROM my_table
WHERE column_b = column_b;
Run Code Online (Sandbox Code Playgroud)
没有索引column_b.
Luk*_*der 12
对于标准的标量数据类型,它们在Oracle上都是相同的(我尝试过12c和11g),因为你获得了相同的执行计划的两倍.(当不是这样时,请参阅MT0对边缘情况的回答)
证明:
CREATE TABLE my_table (columnb NUMBER);
EXPLAIN PLAN FOR
SELECT *
FROM my_table
WHERE columnb IS NOT NULL;
SELECT *
FROM TABLE (dbms_xplan.display);
EXPLAIN PLAN FOR
SELECT *
FROM my_table
WHERE columnb = columnb;
SELECT *
FROM TABLE (dbms_xplan.display);
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,我得到:
Plan hash value: 3804444429
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 2 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| MY_TABLE | 1 | 13 | 2 (0)| 00:00:01 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("COLUMNB" IS NOT NULL)
Run Code Online (Sandbox Code Playgroud)
CREATE INDEX my_index ON my_table (columnb);
Run Code Online (Sandbox Code Playgroud)
...你仍然可以为两个查询获得相同的计划:
Plan hash value: 887433238
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 1 (0)| 00:00:01 |
|* 1 | INDEX FULL SCAN | MY_INDEX | 1 | 13 | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("COLUMNB" IS NOT NULL)
Run Code Online (Sandbox Code Playgroud)
NOT NULL怎么办?我们试试这个:
DROP INDEX my_index; -- Get back to the initial situation
ALTER TABLE my_table MODIFY columnb NUMBER NOT NULL;
Run Code Online (Sandbox Code Playgroud)
我现在得到的计划就是这些,在两种情况下,整个谓词都已被淘汰:
Plan hash value: 3804444429
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| MY_TABLE | 1 | 13 | 2 (0)| 00:00:01 |
------------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
由于你没有从"聪明"的方法中获得任何好处,所以根本不要这样做并将IS NOT NULL谓词写得更清楚.
顺便说一句,这是一个非常有趣的问题和优化类型,我已经在博客上发表了关于它的更多深入的类似优化.