MySQL查詢優化
面試題一
請簡述項目中優化SQL語句執行效率的方法,從那些方面,SQL語句性能如何分析?
優化查詢過程中的數據訪問、優化長難的查詢語句、優化特定類型的查詢語句
分析SQL語句方法
1、使用explain或desc 分析單條SQL語句
列如:explain select * from news;
2、記錄慢查詢日志
分析慢查詢日志,不要直接打開慢查詢日志進行分析,這樣比較浪費時間和精力,可以使用pt-query-disgest工具分析。
3、使用show profile
例如:set profiling = 1;開啟,服務器上執行的所有語句都會檢測消耗的時間,存到臨時表中
show profiles; 顯示臨時表
show profile for query id 查看單挑語句具體執行時間
4、show status
show status 會返回一些計數器,show global status 查看服務器級別的所有計數。
有時根據這些計數,可以猜測出那些操作代價較高或消耗時間多。
5、show processlist
觀察是否右大量線程處於不正常的狀態或者特征
優化查詢過程中
訪問數據太多導致查詢性能下降
確定應用程序是否在檢索大量超過需要的數據,可能時太多行或列
確認MySQL服務器是否在分析大量不必要的數據行
避免使用如下SQL語句
查詢不需要的記錄,使用limit解決
多表關聯返回全部列,指定返回需要的列
總是取出全部列,select * 會讓優化器無法完成索引覆蓋掃描的優化
重復查詢相同的數據,可以把查詢結果做緩存,下次從緩存中獲取數據
是否在掃描額外的記錄?
使用explain進行分析,如果發現查詢需要掃描大量的數據但只返回少數的行,可以通過如下技巧去優化:
使用索引覆蓋掃描,把所有用的列都放到索引中,這樣存儲引擎不需要回表獲取對應行就可以返回結果
改變數據庫和表的結構,修改數據庫范式
重寫SQL語句,讓優化器可以以更優的方式執行查詢
優化長難的查詢語句
一個復雜查詢還是多個簡單查詢、
MySQL內部每秒能掃描內存中上百萬行數據,相比之下,響應數據給客戶端就要慢的多
使用盡可能少的查詢是好的,但是有時將一個大的查詢分解為多個小的查詢是很有必要的
切分查詢
將一個大的查詢分為多個小的相同的查詢
一次性刪除1000萬的數據要比一次刪除1萬,暫停一會的方案更加損耗服務器開銷
分解關聯查詢
可以將一條關聯語句分解成多條SQL來執行
讓緩存的效率更高
執行單個查詢可以減少鎖的競爭
在應用層做關聯可以更容易對數據庫進行拆分
特定類型的查詢
優化count()查詢
count(*) 中的*會忽略所有的列,直接統計所有列數,因此不要使用count(列名)
MyISAM中,沒有任何where條件的count(*)非常快,當有where條件,MyISAM的count統計不一定比其他表引擎快
優化方法
可以使用explain查詢近似值,用近似值替代count(*)
增加匯總表 每次查詢查詢匯總表 , 匯總表使用緩存
優化關聯語句
確定ON或者USING子句的列上有索引
確保GROUP BY 和ORDER BY 中只有一個表中的列,這樣MYSQL才有可能使用索引
優化子查詢
使用關聯查詢替代
優化group by 和 distinct
這兩種查詢均可使用索引來優化,是最有效的優化方法,關聯查詢中,使用標識列進行分組的效率會更高
如果不需要order by ,進行group by 時使用 order by null ,MySQL不會再進行文件排序
with rollup超級聚合,可以挪到應用程序處理
優化limit分頁
limit偏移量大的時候,查詢效率低
可以記錄上次查詢的最大id,下次查詢時直接根據該id查詢
優化union 查詢
union all 的效率高於union