MySQL自定義變數執行順序
高效能MySQL 248頁
關於書中 MySQL自定義變數 確定取值順序的一些實驗和猜測.
並不能保證正確.
實驗資料,test表 a是主鍵,b欄位沒有任何索引.
CREATE TABLE test (
a int(11) NOT NULL,
b int(11) DEFAULT NULL,
PRIMARY KEY (a)
) ENGINE=InnoDB;
INSERT INTO test VALUES (1,100),(2,20),(3,5),(4,40),(5,50);
commit;
第一個例子
檢視如下SQL,按道理應該只有一條記錄,但是卻返回了兩條記錄.
set @rownum:=0;
select a,b,@rownum:=@rownum+1 as cnt
from test
where @rownum<=1;
這是因為自定義變數在SQL執行的不同階段被查詢或運算.
以上面的SQL為例
第一步先獲取一條資料,此時@rownum為0,通過了where條件,在select語句自增後等於1
第二步獲取第二條資料,此時@rownum為1,通過了where條件,在select語句自增後等於2
第三步獲取資料,由於@rownum等於2,不能通過where條件,SQL結束.
第二個例子
如果上面的SQL增加排序,居然返回了全部的資料
set @rownum:=0;
select a,b,@rownum:=@rownum+1 as cnt
from test
where @rownum<=1
order by b;
它的執行計劃如下
這是因為order by引入了檔案排序,而where條件是在檔案排序操作之前取值的.
也就是說,
先執行where條件,這時@rownum為0,所有的記錄都符合條件.
然後排序,並執行select語句對@rownum自增.
第三個例子
有意思的是,如果這時對b欄位建立一個索引,則返回的結果截然不同.
此時的執行計劃
由於b欄位有索引,
先根據索引獲取第一條記錄,此時@rownum為0,通過where條件,然後在select語句對@rownum自增,
然後根據索引獲取第二條資料,此時@rownum為1,通過where條件,然後在select語句自增,這時@rownum已經為2
由於@rownum已經為2,不能通過where條件,SQL結束.
第四個例子
刪除之前例子對欄位b建立的索引
mysql> drop index inx_1 on test;
檢視如下SQL
set @rownum:=0;
select a,b,@rownum as cnt
from test
where (@rownum:=@rownum+1)<=2;
這個結果應該是符合預期的
因為自增@rownum和where條件判斷都在SQL執行的同一階段.
第五個例子
set @rownum:=0;
select a,b,@rownum as cnt
from test
where (@rownum:=@rownum+1)<=1 order by b desc;
它的執行計劃,又見檔案排序.
首先,它獲取第一條記錄,自增@rownum然後判斷where條件,a=1的記錄通過.之後所有的記錄都不能通過where條件.
雖然後續的記錄沒有通過,但是@rownum也會自增.轉入order by 階段之前,@rownum已經等於5了.
然後進入order by 檔案排序階段
最後進入select語句,顯示@rownum為5.
在where中不過濾的結果是這樣的。
如果再次建立欄位b的索引,由於沒有檔案排序的過程,where條件之後,直接進入select語句階段,所以結果如下
第六個例子
再次刪除欄位b上的索引.檢視如下SQL語句
drop index inx_1 on test;
set @rownum:=0;
select a,b,@rownum as cnt
from test
where @rownum<=1
order by b desc,least(0,@rownum:=@rownum+1);
這個結果應該不符合預期
先獲取一個記錄,通過where條件(@rownum=0),進入order by 語句?
再獲取一個記錄,通過where條件(@rownum=1),進入order by 語句?
然後不能通過where條件,SQL結束?
不確定.
但是如果b欄位有索引.
因為MySQL只有升序索引,所以他先從最小值讀取,先通過where條件,然後進入order by語句
所以,order by .. least 的方式,只能用於升序的情況.
這個貓好像15所的小漂啊.
關於書中 MySQL自定義變數 確定取值順序的一些實驗和猜測.
並不能保證正確.
實驗資料,test表 a是主鍵,b欄位沒有任何索引.
CREATE TABLE test (
a int(11) NOT NULL,
b int(11) DEFAULT NULL,
PRIMARY KEY (a)
) ENGINE=InnoDB;
INSERT INTO test VALUES (1,100),(2,20),(3,5),(4,40),(5,50);
commit;
第一個例子
檢視如下SQL,按道理應該只有一條記錄,但是卻返回了兩條記錄.
set @rownum:=0;
select a,b,@rownum:=@rownum+1 as cnt
from test
where @rownum<=1;
這是因為自定義變數在SQL執行的不同階段被查詢或運算.
以上面的SQL為例
第一步先獲取一條資料,此時@rownum為0,通過了where條件,在select語句自增後等於1
第二步獲取第二條資料,此時@rownum為1,通過了where條件,在select語句自增後等於2
第三步獲取資料,由於@rownum等於2,不能通過where條件,SQL結束.
第二個例子
如果上面的SQL增加排序,居然返回了全部的資料
set @rownum:=0;
select a,b,@rownum:=@rownum+1 as cnt
from test
where @rownum<=1
order by b;
它的執行計劃如下
這是因為order by引入了檔案排序,而where條件是在檔案排序操作之前取值的.
也就是說,
先執行where條件,這時@rownum為0,所有的記錄都符合條件.
然後排序,並執行select語句對@rownum自增.
第三個例子
有意思的是,如果這時對b欄位建立一個索引,則返回的結果截然不同.
此時的執行計劃
由於b欄位有索引,
先根據索引獲取第一條記錄,此時@rownum為0,通過where條件,然後在select語句對@rownum自增,
然後根據索引獲取第二條資料,此時@rownum為1,通過where條件,然後在select語句自增,這時@rownum已經為2
由於@rownum已經為2,不能通過where條件,SQL結束.
第四個例子
刪除之前例子對欄位b建立的索引
mysql> drop index inx_1 on test;
檢視如下SQL
set @rownum:=0;
select a,b,@rownum as cnt
from test
where (@rownum:=@rownum+1)<=2;
這個結果應該是符合預期的
因為自增@rownum和where條件判斷都在SQL執行的同一階段.
第五個例子
set @rownum:=0;
select a,b,@rownum as cnt
from test
where (@rownum:=@rownum+1)<=1 order by b desc;
它的執行計劃,又見檔案排序.
首先,它獲取第一條記錄,自增@rownum然後判斷where條件,a=1的記錄通過.之後所有的記錄都不能通過where條件.
雖然後續的記錄沒有通過,但是@rownum也會自增.轉入order by 階段之前,@rownum已經等於5了.
然後進入order by 檔案排序階段
最後進入select語句,顯示@rownum為5.
在where中不過濾的結果是這樣的。
如果再次建立欄位b的索引,由於沒有檔案排序的過程,where條件之後,直接進入select語句階段,所以結果如下
第六個例子
再次刪除欄位b上的索引.檢視如下SQL語句
drop index inx_1 on test;
set @rownum:=0;
select a,b,@rownum as cnt
from test
where @rownum<=1
order by b desc,least(0,@rownum:=@rownum+1);
這個結果應該不符合預期
先獲取一個記錄,通過where條件(@rownum=0),進入order by 語句?
再獲取一個記錄,通過where條件(@rownum=1),進入order by 語句?
然後不能通過where條件,SQL結束?
不確定.
但是如果b欄位有索引.
因為MySQL只有升序索引,所以他先從最小值讀取,先通過where條件,然後進入order by語句
所以,order by .. least 的方式,只能用於升序的情況.
這個貓好像15所的小漂啊.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29254281/viewspace-1415038/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- mysql自定義排序順序語句MySql排序
- 自定義xunit測試用例的執行順序
- mySQL 執行語句執行順序MySql
- sql mysql 執行順序 (4)MySql
- mysql 語句的執行順序MySql
- js函式和變數的執行順序【易錯】JS函式變數
- 如何使用ReentrantLock的條件變數,讓多個執行緒順序執行?ReentrantLock變數執行緒
- Pytest 順序執行,依賴執行,引數化執行
- Sql執行順序SQL
- mysql中自定義變數有哪些MySql變數
- mysql 中sql語句關鍵字的書寫順序與執行順序MySql
- JavaScript是按順序執行的嗎?聊聊JavaScript中的變數提升JavaScript變數
- JavaScript執行順序分析JavaScript
- pipeline的執行順序
- SQL語句執行順序SQL
- Select語句執行順序
- js執行順序Event LoopJSOOP
- Spring Aop的執行順序Spring
- MYSQL學習筆記11: DQL查詢執行順序MySql筆記
- Django Admin自定義app中模型顯示順序DjangoAPP模型
- ansible 變數優先順序示例變數
- async await、Promise、setTimeout執行順序AIPromise
- js解惑-函式執行順序JS函式
- [20191215]seq控制執行順序.txt
- SQL 語句的執行順序SQL
- 關於 Promise 的執行順序Promise
- sql select語法執行順序SQL
- 一個 MySQL sql 語句執行順序帶來的 bugMySql
- 聊聊如何讓springboot攔截器的執行順序按我們想要的順序執行Spring Boot
- join、volatile、newSingleThreadLatch 實現執行緒順序執行thread執行緒
- Java中如何保證執行緒順序執行Java執行緒
- # 關於select關鍵字語句定義順序# 關於select關鍵字語句執行順序
- Nginx 如何自定義變數?Nginx變數
- MySQL 查詢常用操作(0) —— 查詢語句的執行順序MySql
- [20191112]flock控制命令執行順序.txt
- unittest--TestCase 按宣告順序執行
- Go包中程式碼執行順序Go
- kafka多執行緒順序消費Kafka執行緒
- 路由的中介軟體執行順序路由