日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

MySQL SQL優化教程之in和range查詢

瀏覽:34日期:2023-10-08 12:28:24

首先我們來說下in()這種方式的查詢。在《高性能MySQL》里面提及用in這種方式可以有效的替代一定的range查詢,提升查詢效率,因為在一條索引里面,range字段后面的部分是不生效的。使用in這種方式其實MySQL優化器是轉化成了n*m種組合方式來進行查詢,最終將返回值合并,有點類似union但是更高效。同時它存在這一些問題:

老版本的MySQL在IN()組合條件過多的時候會發生很多問題。查詢優化可能需要花很多時間,并消耗大量內存。新版本MySQL在組合數超過一定的數量就不進行計劃評估了,這可能導致MySQL不能很好的利用索引。

這里的“一定數量”在MySQL5.6.5以及以后的版本中是由eq_range_index_dive_limit這個參數控制(感謝@葉金榮同學的指點)。默認設置是10,一直到5.7以后的版本默認會修改成200,當然我們是可以手動設置的。我們看下5.6手冊中的說明:

The eq_range_index_dive_limit system variable enables you to configure the number of values at which the optimizer switches from one row estimation strategy to the other. To disable use of statistics and always use index dives, set eq_range_index_dive_limit to 0. To permit use of index dives for comparisons of up to N equality ranges, set eq_range_index_dive_limit to N + 1.eq_range_index_dive_limit is available as of MySQL 5.6.5. Before 5.6.5, the optimizer uses index dives, which is equivalent to eq_range_index_dive_limit=0.

也就是說:

1. eq_range_index_dive_limit = 0 只能使用index dive2. 0 < eq_range_index_dive_limit <= N 使用index statistics3. eq_range_index_dive_limit > N 只能使用index dive

index dive與index statistics是MySQL優化器對開銷代價的估算方法,前者統計速度慢但是能得到精準的值,后者統計速度快但是數據未必精準。

the optimizer can estimate the row count for each range using dives into the index or index statistics.

在MySQL5.7版本中將默認值從10修改成200目的是為了盡可能的保證范圍等值運算(IN())執行計劃盡量精準,因為IN()list的數量很多時候都是超過10的。

說在前面

今天文章的主題有兩個:

range查詢與索引使用 eq_range_index_dive_limit的說明

range查詢與索引使用

SQL如下:

SELECT * FROM pre_forum_post WHERE tid=7932552 AND `invisible` IN(’0’,’-2’) ORDER BY dateline DESC LIMIT 10;

索引如下:

+----------------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |+----------------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+| pre_forum_post | 0 | PRIMARY | 1 | tid | A | NULL | NULL | NULL | | BTREE | || | pre_forum_post | 0 | PRIMARY | 2 | position | A | 25521392 | NULL | NULL | | BTREE | || | pre_forum_post | 0 | pid | 1 | pid | A | 25521392 | NULL | NULL | | BTREE | || | pre_forum_post | 1 | fid | 1 | fid | A | 1490 | NULL | NULL | | BTREE | || | pre_forum_post | 1 | displayorder | 1 | tid | A | 880048 | NULL | NULL | | BTREE | || | pre_forum_post | 1 | displayorder | 2 | invisible | A | 945236 | NULL | NULL | | BTREE | || | pre_forum_post | 1 | displayorder | 3 | dateline | A | 25521392 | NULL | NULL | | BTREE | || | pre_forum_post | 1 | first | 1 | tid | A | 880048 | NULL | NULL | | BTREE | || | pre_forum_post | 1 | first | 2 | first | A | 1215304 | NULL | NULL | | BTREE | || | pre_forum_post | 1 | new_auth | 1 | authorid | A | 1963184 | NULL | NULL | | BTREE | || | pre_forum_post | 1 | new_auth | 2 | invisible | A | 1963184 | NULL | NULL | | BTREE | || | pre_forum_post | 1 | new_auth | 3 | tid | A | 12760696 | NULL | NULL | | BTREE | || | pre_forum_post | 1 | idx_dt | 1 | dateline | A | 25521392 | NULL | NULL | | BTREE | || | pre_forum_post | 1 | mul_test | 1 | tid | A | 880048 | NULL | NULL | | BTREE | || | pre_forum_post | 1 | mul_test | 2 | invisible | A | 945236 | NULL | NULL | | BTREE | || | pre_forum_post | 1 | mul_test | 3 | dateline | A | 25521392 | NULL | NULL | | BTREE | || | pre_forum_post | 1 | mul_test | 4 | pid | A | 25521392 | NULL | NULL | | BTREE | || +----------------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

看下執行計劃:

root@localhost 16:08:27 [ultrax]> explain SELECT * FROM pre_forum_post WHERE tid=7932552 AND `invisible` IN(’0’,’-2’) -> ORDER BY dateline DESC LIMIT 10;+----+-------------+----------------+-------+-------------------------------------------+--------------+---------+------+------+---------------------------------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+----------------+-------+-------------------------------------------+--------------+---------+------+------+---------------------------------------+| 1 | SIMPLE | pre_forum_post | range | PRIMARY,displayorder,first,mul_test,idx_1 | displayorder | 4 | NULL | 54 | Using index condition; Using filesort | +----+-------------+----------------+-------+-------------------------------------------+--------------+---------+------+------+---------------------------------------+1 row in set (0.00 sec)

MySQL優化器認為這是一個range查詢,那么(tid,invisible,dateline)這條索引中,dateline字段肯定用不上了,也就是說這個SQL最后的排序肯定會生成一個臨時結果集,然后再結果集里面完成排序,而不是直接在索引中直接完成排序動作,于是我們嘗試增加了一條索引。

root@localhost 16:09:06 [ultrax]> alter table pre_forum_post add index idx_1 (tid,dateline); Query OK, 20374596 rows affected, 0 warning (600.23 sec)Records: 0 Duplicates: 0 Warnings: 0root@localhost 16:20:22 [ultrax]> explain SELECT * FROM pre_forum_post force index (idx_1) WHERE tid=7932552 AND `invisible` IN(’0’,’-2’) ORDER BY dateline DESC LIMIT 10;+----+-------------+----------------+------+---------------+-------+---------+-------+--------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+----------------+------+---------------+-------+---------+-------+--------+-------------+| 1 | SIMPLE | pre_forum_post | ref | idx_1 | idx_1 | 3 | const | 120646 | Using where | +----+-------------+----------------+------+---------------+-------+---------+-------+--------+-------------+1 row in set (0.00 sec)root@localhost 16:22:06 [ultrax]> SELECT sql_no_cache * FROM pre_forum_post WHERE tid=7932552 AND `invisible` IN(’0’,’-2’) ORDER BY dateline DESC LIMIT 10;...10 rows in set (0.40 sec)root@localhost 16:23:55 [ultrax]> SELECT sql_no_cache * FROM pre_forum_post force index (idx_1) WHERE tid=7932552 AND `invisible` IN(’0’,’-2’) ORDER BY dateline DESC LIMIT 10;...10 rows in set (0.00 sec)

實驗證明效果是極好的,其實不難理解,上面我們就說了in()在MySQL優化器里面是以多種組合方式來檢索數據的,如果加了一個排序或者分組那勢必只能在臨時結果集上操作,也就是說索引里面即使包含了排序或者分組的字段依然是沒用的。唯一不滿的是MySQL優化器的選擇依然不夠靠譜。

總結下:在MySQL查詢里面使用in(),除了要注意in()list的數量以及eq_range_index_dive_limit的值以外(具體見下),還要注意如果SQL包含排序/分組/去重等等就需要注意索引的使用。

eq_range_index_dive_limit的說明

還是上面的案例,為什么idx_1無法直接使用?需要使用hint強制只用這個索引呢?這里我們首先看下eq_range_index_dive_limit的值。

root@localhost 22:38:05 [ultrax]> show variables like ’eq_range_index_dive_limit’;+---------------------------+-------+| Variable_name | Value |+---------------------------+-------+| eq_range_index_dive_limit | 2 | +---------------------------+-------+1 row in set (0.00 sec)

根據我們上面說的這種情況0 < eq_range_index_dive_limit <= N使用index statistics,那么接下來我們用OPTIMIZER_TRACE來一看究竟。

{ 'index': 'displayorder', 'ranges': [ '7932552 <= tid <= 7932552 AND -2 <= invisible <= -2', '7932552 <= tid <= 7932552 AND 0 <= invisible <= 0' ], 'index_dives_for_eq_ranges': false, 'rowid_ordered': false, 'using_mrr': false, 'index_only': false, 'rows': 54, 'cost': 66.81, 'chosen': true}// index dive為false,最終chosen是true...{ 'index': 'idx_1', 'ranges': [ '7932552 <= tid <= 7932552' ], 'index_dives_for_eq_ranges': true, 'rowid_ordered': false, 'using_mrr': false, 'index_only': false, 'rows': 120646, 'cost': 144776, 'chosen': false, 'cause': 'cost'}

我們可以看到displayorder索引的cost是66.81,而idx_1的cost是120646,而最終MySQL優化器選擇了displayorder這條索引。那么如果我們把eq_range_index_dive_limit設置>N是不是應該就會使用index dive計算方式,得到更準確的執行計劃呢?

root@localhost 22:52:52 [ultrax]> set eq_range_index_dive_limit = 3;Query OK, 0 rows affected (0.00 sec)root@localhost 22:55:38 [ultrax]> explain SELECT * FROM pre_forum_post WHERE tid=7932552 AND `invisible` IN(’0’,’-2’) ORDER BY dateline DESC LIMIT 10;+----+-------------+----------------+------+-------------------------------------------+-------+---------+-------+--------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+----------------+------+-------------------------------------------+-------+---------+-------+--------+-------------+| 1 | SIMPLE | pre_forum_post | ref | PRIMARY,displayorder,first,mul_test,idx_1 | idx_1 | 3 | const | 120646 | Using where | +----+-------------+----------------+------+-------------------------------------------+-------+---------+-------+--------+-------------+1 row in set (0.00 sec)

optimize_trace結果如下

{ 'index': 'displayorder', 'ranges': [ '7932552 <= tid <= 7932552 AND -2 <= invisible <= -2', '7932552 <= tid <= 7932552 AND 0 <= invisible <= 0' ], 'index_dives_for_eq_ranges': true, 'rowid_ordered': false, 'using_mrr': false, 'index_only': false, 'rows': 188193, 'cost': 225834, 'chosen': true}...{ 'index': 'idx_1', 'ranges': [ '7932552 <= tid <= 7932552' ], 'index_dives_for_eq_ranges': true, 'rowid_ordered': false, 'using_mrr': false, 'index_only': false, 'rows': 120646, 'cost': 144776, 'chosen': true}... 'cost_for_plan': 144775, 'rows_for_plan': 120646, 'chosen': true// 在備選索引選擇中兩條索引都被選擇,在最后的邏輯優化中選在了代價最小的索引也就是idx_1

以上就是在等值范圍查詢中eq_range_index_dive_limit的值怎么影響MySQL優化器計算開銷,從而影響索引的選擇。另外我們可以通過profiling來看看優化器的統計耗時:

index dive

+----------------------+----------+| Status| Duration |+----------------------+----------+| starting | 0.000048 | | checking permissions | 0.000004 | | Opening tables | 0.000015 | | init | 0.000044 | | System lock | 0.000009 | | optimizing | 0.000014 | | statistics | 0.032089 | | preparing | 0.000022 | | Sorting result | 0.000003 | | executing | 0.000003 | | Sending data | 0.000101 | | end | 0.000004 | | query end | 0.000002 | | closing tables | 0.000009 | | freeing items | 0.000013 | | cleaning up | 0.000012 | +----------------------+----------+

index statistics

+----------------------+----------+| Status| Duration |+----------------------+----------+| starting | 0.000045 | | checking permissions | 0.000003 | | Opening tables | 0.000014 | | init | 0.000040 | | System lock | 0.000008 | | optimizing | 0.000014 | | statistics | 0.000086 | | preparing | 0.000016 | | Sorting result | 0.000002 | | executing | 0.000002 | | Sending data | 0.000016 | | Creating sort index | 0.412123 | | end | 0.000012 | | query end | 0.000004 | | closing tables | 0.000013 | | freeing items | 0.000023 | | cleaning up | 0.000015 | +----------------------+----------+

可以看到當eq_range_index_dive_limit加大使用index dive時,優化器統計耗時明顯比ndex statistics方式來的長,但最終它使用了作出了更合理的執行計劃。統計耗時0.032089s vs .000086s,但是SQL執行耗時卻是約0.03s vs 0.41s。

附:如何使用optimize_trace

set optimizer_trace=’enabled=on’; select * from information_schema.optimizer_traceG// 注:optimizer_trace建議只在session模式下開啟調試即可

參考資料

http://dev.mysql.com/doc/refman/5.6/en/range-optimization.html

http://imysql.com/2014/08/05/a-fake-bug-with-eq-range-index-dive-limit.shtml

http://blog.163.com/li_hx/blog/static/18399141320147521735442/

到此這篇關于MySQL SQL優化教程之in和range查詢的文章就介紹到這了,更多相關MySQL SQL優化之in和range查詢內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: MySQL 數據庫
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
免费看av不卡| 国产日韩高清一区二区三区在线| 亚洲欧美综合| 国产精品www.| 你懂的亚洲视频| 亚洲精品在线影院| 亚洲国产不卡| 色狠狠一区二区三区| 中文字幕av一区二区三区人| 亚洲免费影院| 日本91福利区| 吉吉日韩欧美| 免费在线观看视频一区| 日本欧美韩国一区三区| 国产精品三上| 欧美激情视频一区二区三区免费| 另类亚洲自拍| 久久精品91| 久久99蜜桃| 日韩大片在线观看| 国产精久久久| 精品日产乱码久久久久久仙踪林| 欧美一区91| 欧美日韩一区自拍| 国产激情久久| 国产一区二区三区亚洲综合| www.51av欧美视频| 精品日韩视频| 美女久久久久| 免费日韩视频| 日韩一区二区三免费高清在线观看| 亚洲麻豆一区| 亚洲欧美日韩专区| 亚洲天堂日韩在线| 国产日本精品| 成人精品久久| 天堂网在线观看国产精品| 香蕉久久国产| 日本v片在线高清不卡在线观看| 日本特黄久久久高潮| 乱一区二区av| 久久精品免费一区二区三区 | 日本久久一区| 九九久久国产| 精品一区二区三区在线观看视频| 中文字幕在线官网| 亚洲综合精品| 国产欧美88| 欧美片第1页| 亚洲精品成a人ⅴ香蕉片| 国产亚洲字幕| 人人香蕉久久| 亚洲三级av| 麻豆精品蜜桃视频网站| 亚洲成a人片| 美女精品在线| 国产精品久久久久久妇女| 波多视频一区| 久久99伊人| 欧美中文高清| 国产精品久久久久av电视剧| 亚洲日本欧美| 日本不良网站在线观看| 久久福利影视| 久久精品国产99国产| 亚洲男女av一区二区| 国产日韩中文在线中文字幕 | 日韩av有码| 丝袜诱惑制服诱惑色一区在线观看| 国产精品中文字幕亚洲欧美 | 大香伊人久久精品一区二区| 激情五月综合网| 91九色综合| 激情久久婷婷| 免费在线欧美黄色| 在线一区欧美| 老色鬼精品视频在线观看播放| 日韩视频中文| 精品视频高潮| 中文字幕日韩亚洲| 欧美成人精品三级网站| 国产午夜久久av| 中文视频一区| 国产一区二区三区久久 | 伊人久久成人| 成午夜精品一区二区三区软件| 亚洲一区二区三区中文字幕在线观看| 国产精品久久久久久久久久10秀| 亚洲日产av中文字幕| 99免费精品| 精品一区二区三区中文字幕视频 | 成人在线视频免费看| 亚洲精品美女91| 久久男人av| 亚洲精品黄色| 欧美一区二区三区激情视频| 国产精品国码视频| 欧美日韩精品在线一区| 日韩视频一区| 天堂网av成人| 久久高清国产| 成人在线视频免费| 久久久久久色 | 久久精品系列| 国产欧美日韩一级| 亚洲专区在线| 免费精品视频| 石原莉奈在线亚洲三区| 午夜视频精品| 精品一区二区三区中文字幕视频| 欧美va天堂| 欧美日韩亚洲一区在线观看| 精品视频高潮| 亚洲精选av| 麻豆精品少妇| 国产精品15p| 日本中文字幕视频一区| 视频小说一区二区| 国产成人精品一区二区三区免费| 久久av资源| 国产麻豆一区二区三区| 久久国产乱子精品免费女| 1024精品久久久久久久久| 亚洲性色av| 欧美aa一级| 九九精品调教| 91精品久久久久久久久久不卡| 黑人精品一区| av资源亚洲| 亚洲性色av| 欧美日韩在线播放视频| 啪啪国产精品| 久久九九国产| 欧美不卡高清| 欧美a级一区| 亚洲精品一二三区区别| 欧美午夜精彩| 中文字幕在线看片| 欧美一级鲁丝片| 久久久精品日韩| 国产一区二区三区四区大秀| 97精品国产福利一区二区三区| 水蜜桃精品av一区二区| 成人福利av| 亚洲天堂久久| 伊人久久亚洲美女图片| 亚洲中字黄色| 国产日韩综合| 日韩精品一级中文字幕精品视频免费观看| 九色精品91| 蜜臀av一区二区三区| 亚洲男人在线| 99国产精品久久久久久久| 日韩亚洲在线| 日韩亚洲精品在线观看| 国产精品白丝一区二区三区| 精品国产一区二区三区av片| 高清av一区| 女生影院久久| 国产福利资源一区| 日韩国产91| 免费在线亚洲| av综合电影网站| 中文一区二区| 亚洲a成人v| 国产精品一级在线观看| 精品一区电影| 精品国产午夜| 精品国产乱码久久久久久樱花| 国产精品99一区二区三区| 欧美一级精品| 91精品视频一区二区| 精品国产99| 在线亚洲自拍| 国产日韩欧美高清免费| 欧美亚洲日本精品| 久久国产亚洲| 亚久久调教视频| 精品久久不卡| 欧美午夜不卡影院在线观看完整版免费| 日韩中文字幕| 成人精品久久| 狠狠爱www人成狠狠爱综合网| 日本在线一区二区三区| 视频在线不卡免费观看| 另类激情亚洲| 国产成人a视频高清在线观看| 亚洲一区中文| 精品中文字幕一区二区三区| 亚洲精华国产欧美| 欧美aa在线视频| av不卡免费看| 成人午夜亚洲| 日欧美一区二区| 91精品一区国产高清在线gif| 日韩精品导航| 99精品视频精品精品视频| 日韩精品一区二区三区中文在线 | 日韩毛片在线| 国产免费av一区二区三区|