select * 比select column快很多奇怪案例分析
遇到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