|
SELECT id FROM customers WHERE type IS NOT Null;7 e* |( k* q# q9 m4 o
相对:0 V* ?* F, `; b0 C/ u
SELECT id FROM customers WHERE NOT type IS NULL;
! y7 \ T5 d, `4 g( U3 y1 D2 N8 F) `以上任一返回的数据将完全相同。; r8 R o5 a9 Q2 ^7 Z% P" K* l; e
有什么区别,为什么其中之一更可取?
( Y8 l" c2 J7 d) k7 U编辑:
0 J, t1 c5 @4 g7 d' {# w7 Z在我看来,性能可能有所不同。有人愿意对此进行详细说明吗?
: S% H& u: X" h/ Q" v
6 q' T5 A; h. Y& O8 ~解决方案:" f2 K. A( R. {9 [
- Z) {8 d/ u$ o# N9 Q" N! _5 ?; G; ~+ H- `+ R, Z
' A# N" {3 b8 b) a8 Z5 ? 没有区别。/ Z0 b6 F1 n1 ^5 B
. H: H6 V6 L8 H1 o! h4 n0 q( j
在我看来,性能可能有所不同。有人愿意对此进行详细说明吗?# `0 R0 y6 n2 r. U( N5 w e/ D
; W3 ^" g( B6 f1 Q' ~3 S, ~
所有主要搜索引擎(即MySQL,SQL Server,Oracle和PostgreSQL)将合并在分析阶段,从他们制作计划相同,这些谓词。
$ k6 Y* e9 w; ^+ u+ c- ~: o这些条件的处理比仅以一个或另一个顺序应用运算符更为复杂。" d4 g$ q3 \- m+ ~# n" m) E
例如,在中Oracle,IS NOT NULL(或NOT IS NULL)条件表示有可能使用索引,因此查询如下:
+ Z* r% e, g9 Z; z1 I. j2 GSELECT column) y; E+ w9 H; h% @ B d
FROM mytable) p0 D" e: \& c* ]1 h% v, d1 i3 c3 J3 N( |
WHERE column IS NOT NULL7 f/ }" J2 l0 G) K
将最有可能使用来执行index fast full
! \' V& F$ V" j" oscan,而在运行时NULL不会进行任何其他检查(因为这些值不会进入索引,因此没有必要对其进行检查)。
! t C" X; v- l& V即使需要检查每个记录,检查的顺序也将由优化器定义(而不是由谓词和运算符出现在WHERE子句中的顺序)。
' {5 N/ i; c' c* o+ q例如,这是一个Oracle查询计划:
y2 T& I9 H( V: d( i b0 j& GSQL> EXPLAIN PLAN FOR
, b0 I8 L b8 L 2 4 ^ a, j# M) P1 t$ U
2 SELECT *0 O2 u z$ K- U3 k
3 FROM t_test1 C6 X6 E1 Z/ D- i" _& }
4 WHERE NOT column IS NULL
3 k8 y ]8 x6 V. U3 O; ?. `, A y 5 / K$ z( s- R6 m1 r; V
Explained
4 W' n! r& E2 P F$ l! }, XSQL> SELECT *2 _& o( F% C- ~! b1 ~3 ~
2 FROM TABLE(DBMS_XPLAN.display())
7 t& ?' \- J7 B1 _ y. s: D$ X 3 /
3 r1 i% a& a- |+ x8 B" d4 g9 \PLAN_TABLE_OUTPUT! v8 U. n, v' T8 H- V1 d
--------------------------------------------------------------------------------- x4 V9 i8 W5 i+ V6 P
Plan hash value: 9586998307 X, i5 s; _, A
----------------------------------------------------------------------------) l6 `" M3 G0 P3 ~* L. c
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
( }* e! Z6 f# o1 l0 P----------------------------------------------------------------------------9 G9 N& T' i+ ?% ]4 p" w
| 0 | SELECT STATEMENT | | 30 | 1260 | 3 (0)| 00:00:01 |4 t8 l) v* c" ^- ^( m0 w3 K7 y! R
|* 1 | TABLE ACCESS FULL| T_TEST | 30 | 1260 | 3 (0)| 00:00:01 |
' v3 P2 P# \; j& |2 r----------------------------------------------------------------------------
6 u. Q, w) O/ F. j) s, GPredicate Information (identified by operation id):. R8 }& Q5 w8 F
---------------------------------------------------
/ h+ X3 \% V% o7 @: A: j 1 - filter("COLUMN" IS NOT NULL)/ g! v+ h! L- j1 R
如您所见,的内容filter已在内部翻译成IS NOT NULL(Oracle与大多数评论者似乎都认为是更合适的形式)' l9 T- P. ~% B, e' }2 z! k
更新:
" |! T* a5 Q4 G, k正如乔纳森·莱夫勒(Jonathan Leffler)所指出的,在评估元组(与单列相对)时,这些是不同的。
4 H+ h- l& _+ B5 u0 f2 Q# n9 V+ J由混合值NULL和非NULL值组成的元组既不是aNULL也不是a NOT NULL。
% q: Q2 Q n4 l' V在PostgreSQL(支持针对元组的谓词)中,这两个表达式:
# \ P+ s1 U' N8 @, b4 B* nSELECT (1, NULL) IS NULL2 f `1 J5 p# N
SELECT (1, NULL) IS NOT NULL( b; T$ p* b! _
评估为假。 |
|