1. 程式人生 > >覆蓋索引--- 一次神奇的MySQL優化 ---select * 效率查的原因

覆蓋索引--- 一次神奇的MySQL優化 ---select * 效率查的原因

話說有這麼一個表:

CREATE TABLE `user_group` (
  `id` int(11) NOT NULL auto_increment,
  `uid` int(11) NOT NULL,
  `group_id` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `uid` (`uid`),
  KEY `group_id` (`group_id`),
) ENGINE=InnoDB AUTO_INCREMENT=750366 DEFAULT CHARSET=utf8

看AUTO_INCREMENT就知道資料並不多,75萬條。然後是一條簡單的查詢:

SELECT SQL_NO_CACHE uid FROM user_group WHERE group_id = 245;

很簡單對不對?怪異的地方在於:

  • 如果換成MyISAM做儲存引擎的時候,查詢耗時只需要0.01s,用InnoDB卻會是0.15s左右

如果只是就這麼點差距其實不是什麼大不了的事,但是真實的業務需求比這個複雜,造成的差距也很大:MyISAM只需要0.12s,InnoDB則需要2.2s.,最終定位到問題癥結是在這條SQL。

Explain的結果是:

+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+
| id | select_type | table      | type | possible_keys | key      | key_len | ref   | rows | Extra |
+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+
|  1 | SIMPLE      | user_group | ref  | group_id      | group_id | 4       | const | 5544 |       |
+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+

看起來已經用上索引了,而這條SQL語句已經簡單到讓我無法再優化了。最後請前同事Gaston診斷了一下,他認為:資料分佈上,group_id相同的比較多,uid雜湊的比較均勻,加索引的效果一般,但是還是建議我試著加了一個多列索引:

ALTER TABLE user_group ADD INDEX group_id_uid (group_id, uid);

然後,不可思議的事情發生了……這句SQL查詢的效能發生了巨大的提升,居然已經可以跑到0.00s左右了。經過優化的SQL再結合真實的業務需求,也從之前2.2s下降到0.05s。

再Explain一次:

+----+-------------+------------+------+-----------------------+--------------+---------+-------+------+-------------+
| id | select_type | table      | type | possible_keys         | key          | key_len | ref   | rows | Extra       |
+----+-------------+------------+------+-----------------------+--------------+---------+-------+------+-------------+
|  1 | SIMPLE      | user_group | ref  | group_id,group_id_uid | group_id_uid | 4       | const | 5378 | Using index
| +----+-------------+------------+------+-----------------------+--------------+---------+-------+------+-------------+

原來是這種叫覆蓋索引(covering index),MySQL只需要通過索引就可以返回查詢所需要的資料,而不必在查到索引之後再去查詢資料,所以那是相當的快!!但是同時也要求所查詢的欄位必須被索引所覆蓋到,在Explain的時候,輸出的Extra資訊中如果有“Using Index”,就表示這條查詢使用了覆蓋索引。

不過,還有一個無法解釋的問題就是,不用覆蓋索引的情況下,為什麼用MyISAM就快那麼多,而InnoDB就慢這麼多呢?求真相……

相關推薦

覆蓋索引--- 神奇MySQL優化 ---select * 效率原因

話說有這麼一個表: CREATE TABLE `user_group` ( `id` int(11) NOT NULL auto_increment, `uid` int(11) NOT NULL, `group_id` int(11) NOT NULL, PRIMARY KEY (`

sql優優化——left join不走索引問題

alt 卡住 image sql col ima cnblogs 優化 .cn sql一執行就卡住,然後就...殺進程了 看了一下表的大小 第一反應就是加索引,然後explain看了一下走什麽索引了,結果很尷尬,三個表,只走了一個索引...一群人在那糾結為毛走不了索引。

神奇的sql查詢經歷,group by慢查詢優化

一、問題背景 現網出現慢查詢,在500萬數量級的情況下,單表查詢速度在30多秒,需要對sql進行優化,sql如下: 我在測試環境構造了500萬條資料,模擬了這個慢查詢。 簡單來說,就是查詢一定條件下,都有哪些使用者的。很簡單的sql,可以看到,查詢耗時為37秒。 說一下app_account欄位

簡單的記錄簡單的優化

原因 循環 返回 嘗試 場景 業務場景 pre 這才 查看 #大致的業務場景 從一個報警表中查詢數據,報警表中有很多其他表的外鍵,比如報警的設備信息信息,報警的組織信息,報警的原件信息等等,也就是說查詢報警信息的時候可以查出來很多相關的信息,需求是參數傳一個組織id,要求查

線上MySQL數據庫死鎖問題

重復 成功 中一 主鍵 adl 一次 his TE BE 最近線上項目報了一個MySQL死鎖(DealLock)錯誤,雖說對業務上是沒有什麽影響的,由於自己對數據庫鎖這塊了解不是很多,之前也沒怎麽的在線上碰到過。這次剛好遇到了,便在此記錄一下。 出現

高併發優化(java)

環境: 1,資料庫:oracle 2,容器:tomcat(apache-tomcat-7.0.85) 期望結果: 1,單臺伺服器結果期望併發800左右; 步驟一:(優化tomcat容器) 1,調整tomcat jvm記憶體大小,以及GC的回收方式,在tomcat資料夾l

【個人小結】資料庫效能優化問題

  需求場景:存在表t_result_changelog,表記錄了caseNo的相關資料,有些caseNo已經被刪除,但表中的資料沒有對應清理。 難點分析:判斷表中哪些資料已經被刪除,需要在對應版本的caseInfo_version中查詢   初次嘗試: 選擇

VUE 專案優化實踐

愛康體檢寶 PC(www.tijianbao.com/) 算是一個“老”專案,為什麼說“老”呢,因為在前端技術日新月異,每天都有新知識、新概念,甚至新框架的今天,它還是基於vue-cli 2.x、webpack 3.x構建,顯然有些老了。其次,在早期開始這個專案的時候,由於倉促上線,也沒有過多的考慮效能及載入

伺服器Tomcat優化經歷

公司需要一臺測試伺服器來做測試用,所以花了點時間把服務全部部署好,在部署好war包之後,發現Tomcat訪問超級慢。 1、進入Tomcat的bin目錄下,執行 ./catalina.sh run命令,在前臺列印執行資訊,首先看其有沒有報錯。好,沒有報錯,進行下一步。 1)修改你的jdk目錄下/

踩坑經歷(五)關於MySQL儲存過程的排錯

SQL語句 -- #開啟定時器,預設為關閉狀態 set global event_scheduler =1; #或者set GLOBAL event_scheduler = ON; use monitorsys; drop event if exists report_back

Webpack 專案優化

本專案原始碼均可在 這裡 找到。 之前公司的官網專案靜態檔案都是放在靜態伺服器中,這其中的弊端就不贅述了。簡單說一下 CDN 的好處: CDN 可以解決因分佈、頻寬、伺服器效能帶來的訪問延遲問題,適用於站點加速、點播、直播等場景。使使用者可就近取得所需內容,解決 Internet 網路擁擠的狀況,提

線上mysql死鎖分析

一、現象 發運車次呼叫發車介面時發生異常,後臺丟擲資料庫死鎖日誌。   二、原因分析   通過日誌可以看出事務T1等待 heap no 8的行鎖 (X locks 排他鎖)                 事務T2持有heap no 8的行鎖,等待heap no 7的行鎖 兩個更新運

安裝mysql-devel帶來的系統問題

  週末安裝qconf時由於glibc版本過低升級了glic後,在做軟連的時不小心錯建了軟連導致整個開發機崩潰,於是開始重灌開發機,由於公司都開始做容器化,因此開發機選用了centos7.2   在編譯完python安裝MYSQL-python過程由於需要依賴mysql-d

哎呀,我老大寫Bug啦——記MessageQueue的優化

  MessageQueue,顧名思義訊息佇列,在系統開發中也是用的比較多的一箇中間件吧。我們這裡主要用它來做日誌管理和訂單管理的,記得老老大(恩,是的,就是老老大,因為他已經跳槽了)還在的時候,當時也是為了趕專案進度,他也參與開發了,那時候我才剛剛入職,他負責寫後端這塊,我來了就把他手上的任務接過來了,(接

mysql服務引發的血案

上午閒玩dos命令,因為dos命令無法啟動mysql服務,於是百度查詢原因,然後從裝了服務。從這裡開始一場沒有硝煙血案就開始了。 從裝mysql服務之後,按原來的方式(原來的使用者名稱密碼)連線資料庫,可是不管怎樣都連線不上 這是什麼原因呢?我想了想,試試不填寫密碼看能不

記憶體洩露優化過程

背景 專案目前存在使用久了或者重複開啟關閉某個頁面,記憶體會一直飆升,居高不下,頻繁發生GC。靜置一段時間後,情況有所改善,但是問題依舊明顯,如圖1-1、1-2。 圖1-1.操作時的記憶體使用情況 圖1-2.靜置時的記憶體使用情況 如上圖1-1,

辛星解讀mysql中獲取排名的例項

     這裡並沒有考慮到繫結,因此我們還是使用拼湊sql語句的形式,而且並不是在mysql命令列中書寫的,很多條件我們都直接用具體的資料來代替。      首先交代一下需求:      (1)作業儲

No buffer space available 神奇的維護經歷

前段時間在專案維護當中遇見一個問題,方便以後再次遇見類似的問題,可以參考解決問題的思路,記錄如下: 問題概述: 維護專案當中,客戶這邊發來訊息,稱自己的網站登入不上去了,提示使用者名稱密碼錯誤,我就登入到伺服器上檢視系統日誌和報錯情況,如圖: 這個異常來源部署的一個jar包,用

使用 Redis 優化查詢效能的實踐

應用背景 有一個應用需要上傳一組ID到伺服器來查詢這些ID所對應的資料,資料庫中儲存的資料量是7千萬,每次上傳的ID數量一般都是幾百至上千數量級別。 以前的解決方案 資料儲存在Oracle中,為ID建立了索引;查詢時,先將這些上傳的ID資料儲存到臨時表中,然後用表關聯的方法來查詢。這樣做的優點是減少了查詢次

25.logstash同步Mysql多張表到ES(ES與關係型資料庫同步)

題記一次同步多張表是開發中的一般需求。之前研究了很久找到方法,但沒有詳細總結。 博友前天線上提問,說明這塊理解的還不夠透徹。 我整理下, 一是為了儘快解決博友問題, 二是加深記憶,便於未來產品開發中快速上手。1、同步原理原有ES專欄中有詳解,不再贅述。詳細請參考我的專欄: 深