2016-07-20 55 views
0

這裏我精簡的情況查詢的限制約束傳播到子查詢

create table t1 (i integer, d text); 
insert into t1 values (0,'aa0'); 
insert into t1 values (1,'aa1'); 
insert into t1 values (2,'aa2'); 
insert into t1 values (3,'aa3'); 
insert into t1 values (4,'aa4'); 
insert into t1 values (5,'aa5'); 
insert into t1 values (6,'aa6'); 
insert into t1 values (7,'aa7'); 
insert into t1 values (8,'aa8'); 
insert into t1 values (9,'aa9'); 

create table t2 (i integer, e text); 
insert into t2 values (0,'aa0'); 
insert into t2 values (1,'ba1'); 
insert into t2 values (2,'aa2'); 
insert into t2 values (3,'ba3'); 
insert into t2 values (4,'aa4'); 
insert into t2 values (5,'ba5'); 
insert into t2 values (6,'aa6'); 
insert into t2 values (7,'ba7'); 
insert into t2 values (8,'aa8'); 
insert into t2 values (9,'ba9'); 

然後我有一個外部SELECT,其目的是打印出來的表格T1的ID的選擇列表(我)

select d from t1 where i in (3,4) limit 4; 
d 
---- 
aa3 
aa4 

的ID集,產生這樣就可以與

select d from t1 where i in (3,4,1,6,7) limit 4; 
d 
---- 
aa1 
aa3 
aa4 
aa6 

最終有時ID組是內SEL的結果ECT子查詢這樣

select d from t1 where i in (select i from t2 where e>'b') limit 4; 
d 
---- 
aa1 
aa3 
aa5 
aa7 

在我的現實情況下,T1和T2是大和內SELECT可以產生一個很大的ID列表,即外部選擇將其限制約束核彈。

我的問題是,查詢優化器是否檢測到這個outrent limit constrainst並將其傳播到內部select中?

如果答案是否定的,那麼我應該走一英里和我的查詢生成器,得到了明確的移動限制約束的內部SELECT這樣

select d from t1 where i in (select i from t2 where e>'b' limit 4); 
d 
---- 
aa1 
aa3 
aa5 
aa7 

問我看着EXPLAIN並解釋查詢之前計劃,但這是超出我的知識,不能從那裏回答。

回答

1

的SQLite沒有optimization,即可以提出一個LIMIT子句爲子查詢,而查詢展平不適用於IN子句。

這證實EXPLAIN(地址22是在外環):

 
sqlite> explain select d from t1 where i in (select i from t2 where e>'b') limit 4; 
addr opcode   p1 p2 p3 p4    p5 comment 
---- ------------- ---- ---- ---- ------------- -- ------------- 
0  Init   0  26 0     00 Start at 26 
1  Integer  4  1  0     00 r[1]=4; LIMIT counter 
2  OpenRead  0  2  0  2    00 root=2 iDb=0; t1 
3  Rewind   0  24 0     00 
4  Noop   0  0  0     00 begin IN expr 
5  Once   0  16 0     00 
6  OpenEphemeral 3  1  0  k(1,B)   00 nColumn=1 
7  OpenRead  1  3  0  2    00 root=3 iDb=0; t2 
8  Rewind   1  15 0     00 
9   Column   1  1  2     00 r[2]=t2.e 
10  Le    3  14 2  (BINARY)  52 if r[3]<=r[2] goto 14 
11  Column   1  0  4     00 r[4]=t2.i 
12  MakeRecord  4  1  5  C    00 r[5]=mkrec(r[4]) 
13  IdxInsert  3  5  0     00 key=r[5] 
14  Next   1  9  0     01 
15  Close   1  0  0     00 
16  Column   0  0  2     00 r[2]=t1.i 
17  IsNull   2  23 0     00 if r[2]==NULL goto 23 
18  Affinity  2  1  0  C    00 affinity(r[2]) 
19  NotFound  3  23 2  1    00 key=r[2]; end IN expr 
20  Column   0  1  6     00 r[6]=t1.d 
21  ResultRow  6  1  0     00 output=r[6] 
22  DecrJumpZero 1  24 0     00 if (--r[1])==0 goto 24 
23 Next   0  4  0     01 
24 Close   0  0  0     00 
25 Halt   0  0  0     00 
26 Transaction 0  0  2  0    01 usesStmtJournal=0 
27 TableLock  0  2  0  t1    00 iDb=0 root=2 write=0 
28 TableLock  0  3  0  t2    00 iDb=0 root=3 write=0 
29 String8  0  3  0  b    00 r[3]='b' 
30 Goto   0  1  0     00 

請注意,LIMIT沒有ORDER BY子句可能不是非常有用,除非你真的想要一個隨機行的樣本。

+0

Thanx CL爲即時回覆。那麼我會照顧LIMIT的位置。在我的情況下,限制只是驗證查詢的一種方式。順序是不相關的,所選擇的ID在內部的選擇是一個正則表達式匹配,則該列表匹配的列表。這有點像「grep foo bifgile | head -4」。我不流利的EXPLAIN的是,和我的實際情況是真正的大,有很多測試沒有發現測試。 – Phi

+0

我應該使用EXPLAIN在我的小測試在這裏,我們對此深感抱歉。 – Phi

+0

你並沒有真正理解EXPLAIN輸出...... –