给定查询:
select * from myTable where 1=0
如果我这样做:
explain query plan <above_query>
它说:
> scan table myTable
这是真的吗它是否真的会执行表扫描(即扫描表中的每一行)?或者它是否实际上跳过table-scan并立即返回一个空的结果集,因为给定的where clause永远不会计算为true
where clause
true
pprl5pva1#
Sqlite准备了一个带有表扫描的计划,但它实际上跳过了整个扫描。如果你执行
explain select * from myTable where 1=0;
你会得到这个编译的计划:
addr opcode p1 p2 p3 p4 p5 comment ---- ------------- ---- ---- ---- ------------- -- ------------- 0 Init 0 9 0 NULL 0 Start at 9 1 Ne 2 8 1 NULL 80 if r[1]!=r[2] goto 8 2 OpenRead 0 2 0 2 0 root=2 iDb=0; t 3 Rewind 0 8 0 NULL 0 NULL 4 Column 0 0 3 NULL 0 r[3]= cursor 0 column 0 5 Column 0 1 4 NULL 0 r[4]= cursor 0 column 1 6 ResultRow 3 2 0 NULL 0 output=r[3..4] 7 Next 0 4 0 NULL 1 NULL 8 Halt 0 0 0 NULL 0 NULL 9 Transaction 0 0 1 0 1 usesStmtJournal=0 10 Integer 1 1 0 NULL 0 r[1]=1 11 Integer 0 2 0 NULL 0 r[2]=0 12 Goto 0 1 0 NULL 0 NULL
它将跳转到第9行,设置事务并将0和1加载到两个寄存器中,然后跳回到第1行。然后,它将比较两个寄存器,发现两个值不同,它将跳到第8行并停止,甚至不打开表。Sqlite没有优化到知道1=0永远不会计算为true,但它确实意识到表达式不依赖于表的任何列,因此它只对整个SELECT计算一次,而不是对每行。
1条答案
按热度按时间pprl5pva1#
Sqlite准备了一个带有表扫描的计划,但它实际上跳过了整个扫描。如果你执行
你会得到这个编译的计划:
它将跳转到第9行,设置事务并将0和1加载到两个寄存器中,然后跳回到第1行。然后,它将比较两个寄存器,发现两个值不同,它将跳到第8行并停止,甚至不打开表。
Sqlite没有优化到知道1=0永远不会计算为true,但它确实意识到表达式不依赖于表的任何列,因此它只对整个SELECT计算一次,而不是对每行。