校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃

主頁 > 知識庫 > SQL優化教程之in與range查詢

SQL優化教程之in與range查詢

熱門標簽:400電話鄭州申請 北京人工外呼系統價錢 常州電銷外呼系統一般多少錢 沃克斯電梯外呼線路圖 房產智能外呼系統品牌 福州呼叫中心外呼系統哪家好 天智外呼系統 云南語音外呼系統平臺 地圖標注被騙三百怎么辦

前言

《高性能MySQL》里面提及用in這種方式可以有效的替代一定的range查詢,提升查詢效率, 因為在一條索引里面,range字段后面的部分是不生效的(ps.需要考慮 ICP) 。MySQL優化器將in這種方式轉化成  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.

換言之,

eq_range_index_dive_limit = 0 只能使用index dive

0 eq_range_index_dive_limit = N 使用index statistics

eq_range_index_dive_limit > N 只能使用index dive

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

在MySQL的官方手冊上有這么一句話:

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

大意:

優化器預估每個范圍段--如"a IN (10, 20, 30)" 視為等值比較, 括3個范圍段實則簡化為3個單值,分別是10,20,30--中包括的元組數,用范圍段來表示是因為 MySQL 的"range"掃描方式多數做的是范圍掃描,此處單值可視為范圍段的特例;

估計方法有2種:

  1. dive到index中即利用索引完成元組數的估算,簡稱index dive;
  2. index statistics:使用索引的統計數值,進行估算;

對比這兩種方式

  1. index dive: 速度慢,但能得到精確的值(MySQL的實現是數索引對應的索引項個數,所以精確)
  2. index statistics: 速度快,但得到的值未必精確

簡單說,**選項 eq_range_index_dive_limit 的值設定了 IN列表中的條件個數上線,超過設定值時,會將執行計劃從 index dive 變成 index statistics **。

為什么要區分這2種方式呢?

  1. 查詢優化器會使用代價估算模型計算每個計劃的代價,選擇其中代價最小的
  2. 單表掃描時,需要計算代價;所以單表的索引掃描也需要計算代價
  3. 單表的計算公式通常是:  代價 = 元組數 * IO平均值
  4. 所以不管是哪種掃描方式,都需要計算元組數
  5. 當遇到“a IN (10, 20, 30)”這樣的表達式的時候,發現a列存在索引,則需要看這個索引可以掃描到的元組數由多少而計算其索引掃描代價,所以就用到了本文提到的“index dive”、“index statistics”這2種方式。

討論主題

  1. range查詢與索引使用
  2. 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;

索引如下:

PRIMARY(tid,position),
pid(pid),
fid(tid),
displayorder(tid,invisible,dateline)
first(tid,first)
new_auth(authorid,invisible,tid)
idx_dt(dateline)
mul_test(tid,invisible,dateline,pid)

看下執行計劃:

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: 0
root@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_trace\G

注:optimizer_trace建議只在session模式下開啟調試即可

如何使用profile

set profiling=ON;
執行sql;
show profiles;
show profile for query 2;
show profile block io,cpu for query 2;

另外還可以看到memory,swaps,context switches,source 等信息

參考資料

[1]MySQL SQL優化系列之 in與range 查詢

https://www.jb51.net/article/201251.htm

[2]MySQL物理查詢優化技術---index dive辨析

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

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

您可能感興趣的文章:
  • 分析MySQL中優化distinct的技巧
  • mysql in語句子查詢效率慢的優化技巧示例
  • MySQL查詢優化:連接查詢排序limit(join、order by、limit語句)介紹
  • MySQL優化之使用連接(join)代替子查詢
  • SQL語句優化之JOIN和LEFT JOIN 和 RIGHT JOIN語句的優化
  • SQL優化之針對count、表的連接順序、條件順序、in及exist的優化
  • MySQL中對于not in和minus使用的優化
  • 關于mysql中innodb的count優化問題分享
  • MySQL中insert語句的使用與優化教程

標簽:徐州 沈陽 珠海 鹽城 移動 拉薩 黔東 沈陽

巨人網絡通訊聲明:本文標題《SQL優化教程之in與range查詢》,本文關鍵詞  SQL,優化,教程,之,與,range,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《SQL優化教程之in與range查詢》相關的同類信息!
  • 本頁收集關于SQL優化教程之in與range查詢的相關信息資訊供網民參考!
  • 推薦文章
    校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃
    成人av电影免费观看| 久久―日本道色综合久久| 精品国产一区久久| 69久久夜色精品国产69蝌蚪网| 91精品婷婷国产综合久久| 亚洲日本va午夜在线影院| 激情偷乱视频一区二区三区| 欧美日韩一区二区三区在线看| 中文无字幕一区二区三区| 日韩二区三区在线观看| 欧美最新大片在线看| 国产精品免费视频网站| 福利电影一区二区| 欧美激情资源网| 成人高清免费在线播放| 中文幕一区二区三区久久蜜桃| 久久精品国产一区二区| 欧美另类高清zo欧美| 亚洲国产日韩一区二区| 欧美性做爰猛烈叫床潮| 亚欧色一区w666天堂| 91麻豆精品国产| 九九热在线视频观看这里只有精品| 悠悠色在线精品| 国产99久久久久| 国产成人精品亚洲777人妖| 欧美丝袜自拍制服另类| 国产亚洲欧美一区在线观看| 中文幕一区二区三区久久蜜桃| 中日韩av电影| 美女在线一区二区| 91在线免费看| 毛片一区二区三区| 久久久久久毛片| 欧美日韩一区中文字幕| 久久99国内精品| 亚洲欧美另类综合偷拍| 欧美日本乱大交xxxxx| 国产一区二区三区视频在线播放| 中文字幕第一页久久| 在线成人免费观看| 成人高清免费在线播放| 男人的j进女人的j一区| 国产精品国产三级国产有无不卡| 在线一区二区三区做爰视频网站| 国产一区日韩二区欧美三区| 亚洲黄网站在线观看| 国产精品人成在线观看免费| 在线播放中文字幕一区| 91麻豆成人久久精品二区三区| 韩国欧美一区二区| 亚洲成人高清在线| 久久综合色婷婷| 亚洲国产精品久久一线不卡| 欧美高清视频一二三区 | 亚洲综合在线第一页| 精品国产成人在线影院| 久草这里只有精品视频| 日日欢夜夜爽一区| 日日摸夜夜添夜夜添国产精品 | 成人av电影在线播放| 日韩精品免费视频人成| 丝瓜av网站精品一区二区| 欧美一级久久久| 久久伊人蜜桃av一区二区| 男男视频亚洲欧美| 国产精品久久久久久久久动漫| 久久―日本道色综合久久| 久久精品视频网| 4hu四虎永久在线影院成人| 在线91免费看| 4438亚洲最大| 制服.丝袜.亚洲.另类.中文| 欧美在线观看视频一区二区三区| av在线不卡免费看| 欧洲一区二区av| 欧美一区二区日韩| 精品少妇一区二区三区在线视频| 久久综合久久99| 国产精品免费视频一区| 亚洲国产精品欧美一二99| 免费欧美在线视频| 国产一区二区中文字幕| 成人黄色软件下载| 欧美一区二区三区影视| 久久精品人人做| 亚洲日本一区二区| 午夜视频一区二区三区| 成人永久看片免费视频天堂| 在线观看免费视频综合| 精品久久久久久久久久久久久久久久久 | 午夜精品成人在线视频| 成人精品gif动图一区| 欧美剧情电影在线观看完整版免费励志电影 | 国产精品福利一区二区三区| 一区二区三区美女视频| 国产不卡视频在线观看| 日韩欧美一区中文| 五月婷婷激情综合网| 豆国产96在线|亚洲| 色综合久久中文综合久久97| 久久久综合九色合综国产精品| 国产欧美日韩不卡| 久久成人羞羞网站| 日韩一级片网址| 日韩激情av在线| 欧美精品久久久久久久多人混战| 日韩毛片精品高清免费| 国产盗摄视频一区二区三区| 精品成人佐山爱一区二区| 欧美96一区二区免费视频| 91精品办公室少妇高潮对白| 日韩美女啊v在线免费观看| 91丨九色丨蝌蚪富婆spa| 日本一区免费视频| 99久精品国产| 亚洲激情图片小说视频| 欧美午夜影院一区| 免费观看日韩电影| 久久精品一级爱片| 成人91在线观看| 午夜日韩在线观看| 欧美一区三区四区| 另类小说欧美激情| 欧美变态凌虐bdsm| 经典三级视频一区| 久久影院视频免费| 91蜜桃在线免费视频| 一区二区在线看| 日韩一区二区电影在线| 男女男精品视频网| 综合久久一区二区三区| 欧美肥妇bbw| 成人一二三区视频| 日韩黄色免费电影| 国产精品网站在线| 日韩免费电影一区| 91黄色免费版| 福利一区二区在线| 亚洲一级二级三级在线免费观看| 日韩欧美电影一区| 91在线精品一区二区三区| 日韩成人免费看| 亚洲激情自拍视频| 亚洲天堂成人在线观看| 久久久精品黄色| 欧美午夜影院一区| 91国模大尺度私拍在线视频| 成人中文字幕电影| 狠狠色丁香九九婷婷综合五月| 亚洲图片一区二区| 一区二区免费在线| 一区二区三区四区在线播放| 欧美成人一区二区三区片免费 | 91精品国产色综合久久不卡蜜臀| 色噜噜狠狠成人中文综合| 成人一级视频在线观看| 国产精品影音先锋| 精品一区中文字幕| 国产传媒一区在线| 国产激情一区二区三区四区| 青娱乐精品在线视频| 黄色成人免费在线| 粉嫩绯色av一区二区在线观看| 国产一区二区看久久| 国产suv精品一区二区883| 成人黄色国产精品网站大全在线免费观看| 精品亚洲porn| 国产福利91精品| 在线免费精品视频| 欧美一级片在线| 欧美高清在线视频| 国产欧美日韩精品a在线观看| 夜夜嗨av一区二区三区| 日韩精品久久久久久| 国产福利一区二区| 欧洲一区在线观看| 久久亚洲捆绑美女| 中文字幕乱码一区二区免费| 天天亚洲美女在线视频| 色婷婷精品久久二区二区蜜臀av| 粉嫩aⅴ一区二区三区四区五区| 国产一区二区在线电影| 国产盗摄女厕一区二区三区| 日韩精品一卡二卡三卡四卡无卡| 亚洲综合久久av| 国产免费成人在线视频| 中文字幕av一区 二区| 欧美成人精品福利| 一区二区三区四区激情| 久久91精品国产91久久小草 | 国产欧美一区二区精品仙草咪| 一区在线播放视频| 国产麻豆精品在线观看| 欧美综合在线视频| 亚洲欧美视频在线观看视频| 日韩国产精品大片| 日韩精品最新网址| 日韩精品免费视频人成| 欧美私人免费视频|