令人頭大的慢查詢分析

令人頭大的慢查詢分析

前言

建表語句

create table student(
  `id`  BIGINT(20)  NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(50) NOT NULL,
  `age`  INT(11)    NOT NULL,
  `height` INT(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `name_index` (`name`),
  KEY `multi_index` (`age`,`height`)  
);

explain命名使用方法

explain命令,主要可以對select語句進行分析,並輸出select執行的詳細信息,以供開發人員針對性優化。explian的使用十分簡單,在select語句前面加上explain關鍵字即可,如下圖,其中order_id是主鍵

輸出的各個屬性含義

id select 查詢的標識符,是唯一的
select_type select查詢類型
table 查詢指定的表
partitions 匹配的分區
type 訪問類型,ALL指的是全表掃描
possible_keys 查詢中可能使用的索引
key 查詢中確切使用到的索引
ref 哪個字段或常數與 key 一起被使用
rows 顯示此查詢一共掃描的行數,是一個估計值.
filtered 查詢條件所過濾的數據的百分比
extra 額外信息

索引失效情況

  • 最佳左前綴法則

    如果索引是複合索引,要遵循最佳左前綴法則,查詢從索引的最前列開始,並且不跳過索引中的列

    下面是違反最佳左前綴法則的情況,針對複合索引(age, height), 直接根據height查詢,則複合索引失效

  • 在索引上做操作(計算、函數、類型轉換),均會導致索引失效

    如下圖,對主鍵id,進行 id+1操作,會使索引失效

  • 索引字段上使用(is null, not null)判斷時,會使索引失效

  • 索引字段使用like以通配符%開頭時,會導致索引失效

  • 索引字段中使用or

慢查詢分析

msql通過指定long_query_time參數,設置慢查詢的時間閾值,一旦查詢語句的執行時間超過此參數,其就會被系統記錄到慢查詢日誌中。通過對慢查詢日誌進行分析,可以對相應的慢查詢語句或者數據庫進行優化,從而提升數據庫性能。下面詳細講述幾種造成慢查詢的原因和優化手段。

  • 上文提到的索引失效

  • limit分頁語句偏移量過大

    limit語句的查詢時間與偏移量成正比,所以一旦偏移量過大會造成查詢速度巨慢

    使用子查詢優化

    原查詢語句

    select * from student limit 200000, 20;

    優化後查詢語句(id是主鍵索引)

    select * from student where id >=(select id from student limit 200000, 1) limit 20;

  • 數據庫在刷髒頁

    數據庫的每一次修改(插入、刪除、更新)操作,都會記錄在redo log日誌,redo log日誌一般不會直接刷新到磁盤中,而是保存在緩衝區(os buffer),等操作系統空閒的時候,刷新進磁盤。但是緩衝區容量是有限的,如果數據庫更新過於頻繁,導致緩衝區滿了,就不會等系統空閒,而是直接暫停其他操作,將緩衝區刷新進磁盤中。所以此時執行查詢語句就會特別慢。

  • 鎖衝突

    數據庫一般支持表鎖,或者行鎖。拿表鎖舉例,如果一個sql語句,獲取表的寫鎖後,在執行更新操作,之後的查詢(select)語句,需要等待表寫鎖釋放,才能獲取讀鎖。

    所以一旦查詢語句執行涉及到的鎖,被其他sql語句佔有,無法獲取鎖,需要等待其釋放鎖,所以會造成查詢慢。

參考文章

騰訊面試:一條SQL語句執行得很慢的原因有哪些?—不看後悔系列

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章