最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

簡單談?wù)凪ySQL的loose index scan

 更新時間:2015年12月11日 12:01:52   投稿:hebedich  
各種資料關(guān)于loose index scan的解釋很拗口,其實等同于oracle的index skip scan。今天我們就來詳細看看loose index scan的使用

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

select count(distinct a) from table1;

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

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

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

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

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

     文檔里關(guān)于group by這里寫的有點意思,說是最大眾化的辦法就是進行全表掃描并且創(chuàng)建一個臨時表,這樣執(zhí)行計劃就會難看的要命了,肯定有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便可返回,源于索引的有序排序,優(yōu)化器意識到min/max位于最左/右塊,從而避免范圍掃描;
extra顯示Select tables optimized away ;
2

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

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

復(fù)制代碼 代碼如下:
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的要求,執(zhí)行計劃的extra顯示using index for group-by,執(zhí)行效果等值于

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

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

Group by何時使用loose index scan?

適用條件:

1  針對單表操作
2  Group by使用索引的最左前綴列
3  只支持聚集函數(shù)min()/max()
4  Where條件出現(xiàn)的列必須為=constant操作 , 沒出現(xiàn)在group by中的索引列必須使用constant
5  不支持前綴索引,即部分列索引 ,如index(c1(10))
執(zhí)行計劃的extra應(yīng)該顯示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, c2
SELECT 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的索引列不連續(xù);或者不是從最左前綴開始,但是where條件里出現(xiàn)最左列;

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)

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

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,從優(yōu)化器層面解決了此類問題。

相關(guān)文章

  • MySQL數(shù)據(jù)庫遷移全過程

    MySQL數(shù)據(jù)庫遷移全過程

    本文詳細解析了MySQL數(shù)據(jù)庫遷移的整個過程,包括準備工作、遷移方法、注意事項和優(yōu)缺點,文章介紹了三種常見的遷移方法:使用mysqldump導(dǎo)出和導(dǎo)入、使用ibd文件遷移和使用目錄整體遷移,每種方法都有其優(yōu)缺點,選擇合適的方法取決于具體的遷移需求和環(huán)境
    2025-02-02
  • MySQL高可用MMM方案安裝部署分享

    MySQL高可用MMM方案安裝部署分享

    這篇文章主要介紹了MySQL高可用MMM方案安裝部署方法,需要的朋友可以參考下
    2014-02-02
  • CentOS 7下使用RPM安裝mysql5.7.13

    CentOS 7下使用RPM安裝mysql5.7.13

    這篇文章主要為大家詳細介紹了CentOS 7下使用RPM安裝mysql5.7.13的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • 如何解決局域網(wǎng)內(nèi)mysql數(shù)據(jù)庫連接慢

    如何解決局域網(wǎng)內(nèi)mysql數(shù)據(jù)庫連接慢

    通過內(nèi)網(wǎng)連另外一臺機器的mysql服務(wù), 確發(fā)現(xiàn)速度N慢! 等了大約幾十秒才等到提示輸入密碼。非常急人,有沒有辦法可以解決局域網(wǎng)內(nèi)mysql數(shù)據(jù)庫連接慢呢?下面小編帶領(lǐng)大家來解決此問題,感興趣的朋友一起看看吧
    2015-09-09
  • MySQL處理重復(fù)數(shù)據(jù)的學(xué)習(xí)筆記

    MySQL處理重復(fù)數(shù)據(jù)的學(xué)習(xí)筆記

    在本篇文章里小編給大家分享的是一篇關(guān)于MySQL處理重復(fù)數(shù)據(jù)的學(xué)習(xí)筆記,需要的朋友們可以參考下。
    2020-03-03
  • Mysql中zerofill自動填充的實現(xiàn)

    Mysql中zerofill自動填充的實現(xiàn)

    MySQL中的zero fill可以設(shè)置自動填充零,以便固定位數(shù)的數(shù)字能夠保持一致的格式,本文就介紹了Mysql中zerofill自動填充,感興趣的可以了解一下
    2023-09-09
  • MySQL數(shù)據(jù)庫遠程連接很慢的解決方案

    MySQL數(shù)據(jù)庫遠程連接很慢的解決方案

    本文給大家分享的是MySQL數(shù)據(jù)庫遠程連接很慢的解決方法,簡單的說就是開啟skip-name-resolve,非常的簡單實用,有需要的小伙伴可以參考下
    2016-12-12
  • 在Windows系統(tǒng)上使用壓縮歸檔文件安裝MySQL的步驟

    在Windows系統(tǒng)上使用壓縮歸檔文件安裝MySQL的步驟

    這篇文章主要介紹了在Windows系統(tǒng)上使用壓縮歸檔文件安裝MySQL的步驟,非常不錯,具有一定的參考借鑒加載,需要的朋友可以參考下
    2018-06-06
  • CentOS 7下安裝與配置MySQL 5.7

    CentOS 7下安裝與配置MySQL 5.7

    Mysql5.7和之前版本的MySQL有一些不同,現(xiàn)把CentOS 7下MySQL 5.7安裝、配置完整過程記下來,或許對新手來說有用。希望大家能夠喜歡
    2018-01-01
  • MySQL將版本由5.7.37更新到5.7.39的實現(xiàn)方式

    MySQL將版本由5.7.37更新到5.7.39的實現(xiàn)方式

    這篇文章主要介紹了MySQL將版本由5.7.37更新到5.7.39的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12

最新評論

宁阳县| 石狮市| 兰州市| 河西区| 白朗县| 抚宁县| 阿拉善右旗| 揭西县| 东城区| 遂昌县| 肥城市| 禹城市| 恩施市| 乐昌市| 博罗县| 南宁市| 竹溪县| 九江县| 泰兴市| 山阴县| 沧源| 东阳市| 华安县| 乌审旗| 密云县| 句容市| 绥宁县| 唐山市| 九寨沟县| 雷州市| 奉节县| 响水县| 丹凤县| 武安市| 新绛县| 宜州市| 沧州市| 安陆市| 安化县| 新乡市| 金沙县|