遇到MYSQL傻傻的地方,下面給個案例,大家感受下:
注意以下兩個sql只有select *和select g.id區別。
SQL1:
SELECT
g.id
FROM
table1 g
INNER JOIN table2 l ON concat('訂單號:',CONVERT(g.id,char)) = l.info
WHERE LOCATE('付款操作',l.info) AND g.p = 2
LIMIT 100
查詢時間:5.28s
SQL2:
SELECT
*
FROM
table1 g
INNER JOIN table2 l ON concat('訂單設為付款操作成功 訂單號:',CONVERT(g.id,char)) = l.info
WHERE LOCATE('付款操作成功',l.info) AND g.p = 2
LIMIT 100
查詢時間:0.21s
注意以下Sending data的sql1比sql2慢,這是不是很詭異!!!!!!!!!!!!!!
SQL1:
SQL2:
分析下profile的情況:
sql1的Context_voluntary | Context_involuntary | Block_ops_in | Block_ops_out 比sql2的高很多,按理說字段少,處理數據更快啊!這里為什么反而更慢?????
Context_voluntary :這個是主動上下文切換次數
Context_involuntary :這個是被動上下文切換次數
Block_ops_in :這個是阻塞輸入操作
Block_ops_out :這個是阻塞輸出操作
下面說下原因為什么select column比select *慢:
1.select column比select *處理的數據少
2.mysql的select操作使用的是悲觀鎖
3.cpu對select column的處理速度要快於select *
4.導致cpu處理完一批數據,ops_in 跟不上,而使用悲觀鎖,cpu不會自旋,等待數據,而是切換到其它任務
5.所以數據量少的上下文切換的更頻繁
6.所以select * 比select column快了很多
解決辦法:
多加幾個字段,增加數據量,這樣cpu就沒有等待,進行的上下文切換就會少很多,速度就會快很多。如果應用嫌獲得數據太多,應用層獲得數據把這些數據進行過濾掉就行了。最好的辦法是拆分字段,使查詢走索引。
SELECT
g.id,g.column1,g.cloumn2
FROM
table1 g
INNER JOIN table2 l ON concat('訂單號:',CONVERT(g.id,char)) = l.info
WHERE LOCATE('付款操作',l.info) AND g.p = 2
LIMIT 100