覆蓋索引--- 一次神奇的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專欄中有詳解,不再贅述。詳細請參考我的專欄: 深