亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > MySQL > 正文

簡單談談MySQL的loose index scan

2024-07-24 13:08:21
字體:
來源:轉載
供稿:網友
各種資料關于loose index scan的解釋很拗口,其實等同于oracle的index skip scan。今天我們就來詳細看看loose index scan的使用
 

眾所周知,InnoDB采用IOT(index organization table)即所謂的索引組織表,而葉子節點也就存放了所有的數據,這就意味著,數據總是按照某種順序存儲的。所以問題來了,如果是這樣一個語句,執行起來應該是怎么樣的呢?語句如下:

select count(distinct a) from table1;

     列a上有一個索引,那么按照簡單的想法來講,如何掃描呢?很簡單,一條一條的掃描,這樣一來,其實做了一次索引全掃描,效率很差。這種掃描方式會掃描到很多很多的重復的索引,這樣說的話優化的辦法也是很容易想到的:跳過重復的索引就可以了。于是網上能搜到這樣的一個優化的辦法:

select count(*) from (select distinct a from table1) t;

    從已經搜索到的資料看,這樣的執行計劃中的extra就從using index變成了using index for group-by。

    但是,但是,但是,好在我們現在已經沒有使用5.1的版本了,大家基本上都是5.5以上了,這些現代版本,已經實現了loose index scan:

     很好很好,就不需要再用這種奇技淫巧去優化SQL了。

     文檔里關于group by這里寫的有點意思,說是最大眾化的辦法就是進行全表掃描并且創建一個臨時表,這樣執行計劃就會難看的要命了,肯定有ALL和using temporary table了。

5.0之后group by在特定條件下可能使用到loose index scan,

CREATE TABLE log_table (id INT NOT NULL PRIMARY KEY,log_machine VARCHAR(20) NOT NULL,log_time DATETIME NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE INDEX ix_log_machine_time ON log_table (log_machine, log_time);

1

SELECT MAX(log_time) FROM log_table;SELECT MAX(log_time) FROM log_table WHERE log_machine IN ('Machine 1');

這兩條sql都只需一次index seek便可返回,源于索引的有序排序,優化器意識到min/max位于最左/右塊,從而避免范圍掃描;
extra顯示Select tables optimized away ;
2

復制代碼代碼如下:
SELECT MAX(log_time) FROM log_table WHERE log_machine IN (‘Machine 1','Machine 2','Machine 3','Machine 4');

 

執行計劃type 為range(extra顯示using where; using index),即執行索引范圍掃描,先讀取所有滿足log_machine約束的記錄,然后對其遍歷找出max value;
改進

復制代碼代碼如下:
SELECT MAX(log_time) FROM log_table WHERE log_machine IN (‘Machine 1','Machine 2','Machine 3','Machine 4')  group by log_machine order by 1 desc limit 1;

這滿足group by選擇loose index scan的要求,執行計劃的extra顯示using index for group-by,執行效果等值于

 

SELECT MAX(log_time) FROM log_table WHERE log_machine IN (‘Machine 1')UnionSELECT MAX(log_time) FROM log_table WHERE log_machine IN (‘Machine 2')…..

即對每個log_machine執行loose index scan,rows從原來的82636下降為16(該表總共1,000,000條記錄)。

Group by何時使用loose index scan?

適用條件:

1  針對單表操作
2  Group by使用索引的最左前綴列
3  只支持聚集函數min()/max()
4  Where條件出現的列必須為=constant操作 , 沒出現在group by中的索引列必須使用constant
5  不支持前綴索引,即部分列索引 ,如index(c1(10))
執行計劃的extra應該顯示using index for group-by
假定表t1有個索引idx(c1,c2,c3)

SELECT c1, c2 FROM t1 GROUP BY c1, c2;SELECT DISTINCT c1, c2 FROM t1;SELECT c1, MIN(c2) FROM t1 GROUP BY c1;SELECT c1, c2 FROM t1 WHERE c1 < const GROUP BY c1, c2;SELECT MAX(c3), MIN(c3), c1, c2 FROM t1 WHERE c2 > const GROUP BY c1, c2;SELECT c2 FROM t1 WHERE c1 < const GROUP BY c1, c2;SELECT c1, c2 FROM t1 WHERE c3 = const GROUP BY c1, c2SELECT c1, c3 FROM t1 GROUP BY c1, c2;--無法使用松散索引

而SELECT c1, c3 FROM t1  where c3= const GROUP BY c1, c2;則可以

緊湊索引掃描tight index scan
Group by在無法使用loose index scan,還可以選擇tight,若兩者都不可選,則只能借助臨時表;
掃描索引時,須讀取所有滿足條件的索引鍵,要么是全索引掃描,要么是范圍索引掃描;
Group by的索引列不連續;或者不是從最左前綴開始,但是where條件里出現最左列;

SELECT c1, c2, c3 FROM t1 WHERE c2 = 'a' GROUP BY c1, c3;SELECT c1, c2, c3 FROM t1 WHERE c1 = 'a' GROUP BY c2, c3;

5.6的改進
事實上,5.6的index condition push down可以彌補loose index scan缺失帶來的性能損失。
KEY(age,zip)

mysql> explain SELECT name FROM people WHERE age BETWEEN 18 AND 20 AND zip IN (12345,12346, 12347);+----+-------------+--------+-------+---------------+------+---------+------+-------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra    |+----+-------------+--------+-------+---------------+------+---------+------+-------+-------------+| 1 | SIMPLE   | people | range | age      | age | 4    | NULL | 90556 | Using where |+----+-------------+--------+-------+---------------+------+---------+------+-------+-------------+1 row in set (0.01 sec)

根據key_len=4可以推測出sql只用到索引的第一列,即先通過索引查出滿足age (18,20)的行記錄,然后從server層篩選出滿足zip約束的行;
pre-5.6,對于復合索引,只有當引導列使用"="時才有機會在索引掃描時使用到后面的索引列。

mysql> explain SELECT name FROM people WHERE age=18 AND zip IN (12345,12346, 12347);+----+-------------+--------+-------+---------------+------+---------+------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra    |+----+-------------+--------+-------+---------------+------+---------+------+------+-------------+| 1 | SIMPLE   | people | range | age      | age | 8    | NULL |  3 | Using where |+----+-------------+--------+-------+---------------+------+---------+------+------+-------------+1 row in set (0.00 sec)

對比一下查詢效率

mysql> SELECT sql_no_cache name FROM people WHERE age=19 AND zip IN (12345,12346, 12347);+----------------------------------+| name               |+----------------------------------+| 888ba838661aff00bbbce114a2a22423 |+----------------------------------+1 row in set (0.06 sec)mysql> SELECT SQL_NO_CACHE name FROM people WHERE age BETWEEN 18 AND 22 AND zip IN (12345,12346, 12347);+----------------------------------+| name               |+----------------------------------+| ed4481336eb9adca222fd404fa15658e || 888ba838661aff00bbbce114a2a22423 |+----------------------------------+2 rows in set (1 min 56.09 sec)

對于第二條sql,可以使用union改寫,

mysql> SELECT name FROM people WHERE age=18 AND zip IN (12345,12346, 12347)  -> UNION ALL  -> SELECT name FROM people WHERE age=19 AND zip IN (12345,12346, 12347)  -> UNION ALL  -> SELECT name FROM people WHERE age=20 AND zip IN (12345,12346, 12347)  -> UNION ALL  -> SELECT name FROM people WHERE age=21 AND zip IN (12345,12346, 12347)  -> UNION ALL-> SELECT name FROM people WHERE age=22 AND zip IN (12345,12346, 12347);

而mysql5.6引入了index condition pushdown,從優化器層面解決了此類問題。



注:相關教程知識閱讀請移步到MYSQL教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
免费91麻豆精品国产自产在线观看| 韩国精品美女www爽爽爽视频| 国产精品一区二区三区久久| 伊人伊成久久人综合网小说| 亚洲激情电影中文字幕| 亚洲级视频在线观看免费1级| 日韩激情在线视频| 久久影视免费观看| 国产91在线播放| 欧美视频在线免费看| 91精品国产乱码久久久久久蜜臀| 亚洲韩国欧洲国产日产av| 精品国产一区二区三区久久狼黑人| 亚洲字幕在线观看| 亚洲美女黄色片| 亚洲欧美在线磁力| 在线日韩第一页| 亚洲影影院av| 欧美在线国产精品| 欧美影院在线播放| 亚洲电影天堂av| 久久精品国产96久久久香蕉| 亚洲欧美一区二区精品久久久| 丰满岳妇乱一区二区三区| 欧美大尺度激情区在线播放| 中文字幕精品—区二区| 富二代精品短视频| 久久免费成人精品视频| 国产精品r级在线| 亚洲一区二区免费| 51视频国产精品一区二区| 欧美国产精品日韩| 久久国产天堂福利天堂| 亚洲欧美日韩精品久久亚洲区| 2018国产精品视频| 日韩福利伦理影院免费| 国产精品手机播放| 欧美视频在线免费| 国产日韩欧美在线看| 日本三级久久久| 欧美激情精品久久久久久蜜臀| 成人性教育视频在线观看| 夜夜嗨av色综合久久久综合网| 久热爱精品视频线路一| 4438全国成人免费| 国产精品久久久久久久久久| 最新亚洲国产精品| 久久久久久国产免费| 国产精品久久国产精品99gif| 日本欧美中文字幕| 国产精品女视频| 911国产网站尤物在线观看| 国产欧美日韩高清| 欧美亚洲在线观看| 美女久久久久久久久久久| 成人久久一区二区| 久久久久久久一区二区三区| 中文字幕av一区| 亚洲三级免费看| 亚洲国产天堂久久综合网| 中文字幕欧美精品在线| 青青草精品毛片| 亚洲黄色在线看| 一本大道久久加勒比香蕉| 播播国产欧美激情| 欧洲成人免费aa| 国产国产精品人在线视| 亚洲国产成人在线视频| 成人性生交大片免费看小说| 日韩电影免费在线观看| 亚洲韩国青草视频| 国产精品福利片| 亚洲免费视频网站| 欧美国产极速在线| 日韩亚洲精品电影| 波霸ol色综合久久| 国产精品美女视频网站| 精品成人国产在线观看男人呻吟| 一区二区亚洲欧洲国产日韩| 久久亚洲精品国产亚洲老地址| 国产欧美日韩亚洲精品| 欧美激情视频在线观看| 国产97在线|亚洲| 日韩精品在线影院| 久久久久五月天| 精品国产一区二区三区在线观看| 亚洲久久久久久久久久| 亚洲精品一区二区网址| 亚洲成色777777女色窝| 国产精品视频999| 日韩麻豆第一页| 久久视频免费观看| 国产91成人在在线播放| 欧美日韩国产在线| 91中文字幕在线| 中文字幕亚洲图片| 久久这里有精品视频| www日韩中文字幕在线看| 久久精品在线视频| 伊人久久综合97精品| 精品中文字幕久久久久久| 欧美亚洲在线播放| 国产一区二区三区丝袜| 色视频www在线播放国产成人| 亚洲另类xxxx| 欧美国产日产韩国视频| 欧美—级高清免费播放| 亚洲精品suv精品一区二区| 日韩亚洲一区二区| 欧美三级欧美成人高清www| 成人福利在线视频| 久久久久久高潮国产精品视| 国产精品视频精品视频| 日韩**中文字幕毛片| 亚洲精品久久久一区二区三区| 国产精品丝袜久久久久久不卡| 北条麻妃99精品青青久久| 亚洲成人黄色在线| 成人免费大片黄在线播放| 国产丝袜一区二区三区| 最近2019中文字幕mv免费看| 欧美日韩美女视频| 国产97在线|亚洲| 欧美成人三级视频网站| 亚洲va男人天堂| 57pao国产成人免费| 亚洲人精品午夜在线观看| 国产乱人伦真实精品视频| 日本国产一区二区三区| 日韩成人xxxx| 欧美成年人视频网站欧美| 中文字幕亚洲在线| 亚洲国产高潮在线观看| 亚洲国产精品99| 热99精品里视频精品| 精品女同一区二区三区在线播放| 中文字幕日韩av综合精品| 日韩av不卡电影| 米奇精品一区二区三区在线观看| 国产视频自拍一区| 久久精品久久精品亚洲人| 正在播放亚洲1区| 国模私拍一区二区三区| 成人福利在线观看| 久久精品电影网站| 中文字幕久精品免费视频| 欧美午夜宅男影院在线观看| 国产日韩在线视频| 夜夜嗨av色综合久久久综合网| 国产一区二区日韩精品欧美精品| 国产精品久久久av| 一区二区三区精品99久久| 欧美日韩成人在线视频| 精品国产成人av| 中文欧美日本在线资源| 亚洲国产91色在线| 日本精品一区二区三区在线播放视频| 日本人成精品视频在线| 国产精品国产三级国产专播精品人| 日韩欧美在线视频日韩欧美在线视频| 亚洲自拍偷拍色片视频| 亚洲免费精彩视频| 在线视频欧美性高潮| 91国产精品视频在线|