电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

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

MySQL SQL優(yōu)化教程之in和range查詢

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

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

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

這里的“一定數(shù)量”在MySQL5.6.5以及以后的版本中是由eq_range_index_dive_limit這個參數(shù)控制(感謝@葉金榮同學的指點)。默認設置是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優(yōu)化器對開銷代價的估算方法,前者統(tǒng)計速度慢但是能得到精準的值,后者統(tǒng)計速度快但是數(shù)據(jù)未必精準。

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

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

看下執(zhí)行計劃:

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優(yōu)化器認為這是一個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優(yōu)化器里面是以多種組合方式來檢索數(shù)據(jù)的,如果加了一個排序或者分組那勢必只能在臨時結果集上操作,也就是說索引里面即使包含了排序或者分組的字段依然是沒用的。唯一不滿的是MySQL優(yōu)化器的選擇依然不夠靠譜。

總結下:在MySQL查詢里面使用in(),除了要注意in()list的數(shù)量以及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)

根據(jù)我們上面說的這種情況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優(yōu)化器選擇了displayorder這條索引。那么如果我們把eq_range_index_dive_limit設置>N是不是應該就會使用index dive計算方式,得到更準確的執(zhí)行計劃呢?

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// 在備選索引選擇中兩條索引都被選擇,在最后的邏輯優(yōu)化中選在了代價最小的索引也就是idx_1

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

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時,優(yōu)化器統(tǒng)計耗時明顯比ndex statistics方式來的長,但最終它使用了作出了更合理的執(zhí)行計劃。統(tǒng)計耗時0.032089s vs .000086s,但是SQL執(zhí)行耗時卻是約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優(yōu)化教程之in和range查詢的文章就介紹到這了,更多相關MySQL SQL優(yōu)化之in和range查詢內容請搜索好吧啦網以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

相關文章:
主站蜘蛛池模板: 二手注塑机回收_旧注塑机回收_二手注塑机买卖 - 大鑫二手注塑机 二手光谱仪维修-德国OBLF光谱仪|进口斯派克光谱仪-热电ARL光谱仪-意大利GNR光谱仪-永晖检测 | 窖井盖锯圆机_锯圆机金刚石锯片-无锡茂达金刚石有限公司 | 净化车间_洁净厂房_净化公司_净化厂房_无尘室工程_洁净工程装修|改造|施工-深圳净化公司 | 焦作网 WWW.JZRB.COM | 污水/卧式/潜水/钻井/矿用/大型/小型/泥浆泵,价格,参数,型号,厂家 - 安平县鼎千泵业制造厂 | 雨燕360体育免费直播_雨燕360免费NBA直播_NBA篮球高清直播无插件-雨燕360体育直播 | 恒温油槽-恒温水槽-低温恒温槽厂家-宁波科麦仪器有限公司 | 广州物流公司_广州货运公司_广州回程车运输 - 万信物流 | 氟氨基酮、氯硝柳胺、2-氟苯甲酸、异香兰素-新晨化工 | 宁夏档案密集柜,智能密集柜,电动手摇密集柜-盛隆柜业宁夏档案密集柜厂家 | 宿松新闻网 宿松网|宿松在线|宿松门户|安徽宿松(直管县)|宿松新闻综合网站|宿松官方新闻发布 | 塑料检查井_双扣聚氯乙烯增强管_双壁波纹管-河南中盈塑料制品有限公司 | 高温热泵烘干机,高温烘干热泵,热水设备机组_正旭热泵 | 台式核磁共振仪,玻璃软化点测定仪,旋转高温粘度计,测温锥和测温块-上海麟文仪器 | 内窥镜-工业内窥镜厂家【上海修远仪器仪表有限公司】 | 济南ISO9000认证咨询代理公司,ISO9001认证,CMA实验室认证,ISO/TS16949认证,服务体系认证,资产管理体系认证,SC食品生产许可证- 济南创远企业管理咨询有限公司 郑州电线电缆厂家-防火|低压|低烟无卤电缆-河南明星电缆 | 硬质合金模具_硬质合金非标定制_硬面加工「生产厂家」-西迪技术股份有限公司 | 土壤养分检测仪_肥料养分检测仪_土壤水分检测仪-山东莱恩德仪器 大型多片锯,圆木多片锯,方木多片锯,板材多片锯-祥富机械有限公司 | 岩棉板|岩棉复合板|聚氨酯夹芯板|岩棉夹芯板|彩钢夹芯板-江苏恒海钢结构 | IWIS链条代理-ALPS耦合透镜-硅烷预处理剂-上海顶楚电子有限公司 lcd条形屏-液晶长条屏-户外广告屏-条形智能显示屏-深圳市条形智能电子有限公司 | 没斑啦-专业的祛斑美白嫩肤知识网站-去斑经验分享 | 北京翻译公司-专业合同翻译-医学标书翻译收费标准-慕迪灵 | 山东风淋室_201/304不锈钢风淋室净化设备厂家-盛之源风淋室厂家 翻斗式矿车|固定式矿车|曲轨侧卸式矿车|梭式矿车|矿车配件-山东卓力矿车生产厂家 | 全自动包衣机-无菌分装隔离器-浙江迦南科技股份有限公司 | 尼龙PA610树脂,尼龙PA612树脂,尼龙PA1010树脂,透明尼龙-谷骐科技【官网】 | 北京亦庄厂房出租_经开区产业园招商信息平台| 耐破强度测试仪-纸箱破裂强度试验机-济南三泉中石单品站 | 福建成考网-福建成人高考网 | 铝合金电阻-无源谐波滤波器-上海稳达电讯设备厂 | 脱硝喷枪-氨水喷枪-尿素喷枪-河北思凯淋环保科技有限公司 | 蒸汽吸附分析仪-进口水分活度仪|康宝百科 | 济南侦探调查-济南调查取证-山东私家侦探-山东白豹调查咨询公司 密集架|电动密集架|移动密集架|黑龙江档案密集架-大量现货厂家销售 | 计算机毕业设计源码网| 奇酷教育-Python培训|UI培训|WEB大前端培训|Unity3D培训|HTML5培训|人工智能培训|JAVA开发的教育品牌 | 彩信群发_群发彩信软件_视频短信营销平台-达信通 | 赛尔特智能移动阳光房-阳光房厂家-赛尔特建筑科技(广东)有限公司 | 动物麻醉机-数显脑立体定位仪-北京易则佳科技有限公司 | 卷筒电缆-拖链电缆-特种柔性扁平电缆定制厂家「上海缆胜」 | 电线电缆厂家|沈阳电缆厂|电线厂|沈阳英联塑力线缆有限公司 | 食品质构分析仪-氧化诱导分析仪-瞬态法导热系数仪|热冰百科 | 100_150_200_250_300_350_400公斤压力空气压缩机-舰艇航天配套厂家 |