MYSQL "ORDER BY rand()"的坑--容易導致機器負載、CPU佔用過高
在一次微信砍價活動營銷中,使用了4核16G10M頻寬的伺服器支撐業務,本來這個配置跑個PHP+MYSQL+nginx肯定輕輕鬆的事情,可是隨著活動的高潮,併發數一高,機器負載核CPU一下子就達到100%
始終找不到原因,只知道是mysql分配的記憶體不夠,一直給它加,但是重啟mysqld服務之後不久又會再次出現負載100%,頁面載入龜速的問題。後來通過SQL分析找到了問題:
分析:
執行語句:show full processlist; 顯示哪些執行緒正在執行。
上面是個列表,我只截有問題的語句,大家可以把正在執行的執行緒具體語句都抓出來排查
這句話完整sql語句是
$sql = " SELECT * FROM ".tablename('mc_mapping_fans')." ORDER BY rand() LIMIT 3 ";
然後再分析它
EXPLAIN SELECT * FROM `ims_mc_mapping_fans` ORDER BY rand() LIMIT 3;
可以看到為什麼它會卡,涉及的行列有60000多行,隨機取3個結果出來,我是每個頁面點進去都隨機抓3條出來展示,而且是3秒一次,這有肯定會造成伺服器卡死!
問題找到了,趕緊做測試,把語句由
$sql = " SELECT * FROM ".tablename('mc_mapping_fans')." ORDER BY rand() LIMIT 3 ";
改為
$sql = " SELECT * FROM ".tablename('mc_mapping_fans')." LIMIT 3 ";
去掉ORDER BY rand(),儲存。
再看CPU、負載情況:
一片健康的指標,問題終於解決了!修改儲存後可看到寶塔面板裡的負載、cpu使用率噌噌往下降。
結尾:ORDER BY rand() 在查詢範圍大的情況下會增大伺服器負載和增大查詢時間,不要輕易使用,可以採取其他隨機函式,比如select max(id)之類的,網上可以查到這方面的許多材料,就不多說了。最後感謝專業運維好兄弟 瑞哥 的幫助!希望此篇教程可以幫到遇到類似問題的小夥伴。