作者:边城元元

原文来源: https://tidb.net/blog/f3ae08ad

一、背景

在分布式数据库中数据量级大都在千万以上,用到的最多的sql类似 where ,order by ,limit 的语句。

where,order by的字段能否同时走索引呢?带着这个疑问基于 TiDBV6.0 做一个实验验证。

二、环境准备

2.1 建立TiDB cluster111

  • 拓扑如下(cluster111-full.yaml)
global:user: "tidb"ssh_port: 22deploy_dir: "/tidb-deploy"data_dir: "/tidb-data"
​
# # Monitored variables are applied to all the machines.
monitored:node_exporter_port: 9100blackbox_exporter_port: 9115
​
server_configs:tidb:log.slow-threshold: 300binlog.enable: falsebinlog.ignore-error: falsetikv:readpool.storage.use-unified-pool: falsereadpool.coprocessor.use-unified-pool: truepd:schedule.leader-schedule-limit: 4schedule.region-schedule-limit: 2048schedule.replica-schedule-limit: 64replication.location-labels:- host
​
pd_servers:- host: 10.0.2.15# ssh_port: 22# name: "pd-1"client_port: 2379# peer_port: 2380
​
​
tidb_servers:- host: 10.0.2.15
​
​
tikv_servers:- host: 10.0.2.15# ssh_port: 22port: 20160status_port: 20180config:server.grpc-concurrency: 4#server.labels: {host: "10.0.2.15.20160" }
​
monitoring_servers:- host: 10.0.2.15
​
grafana_servers:- host: 10.0.2.15
​
alertmanager_servers:- host: 10.0.2.15
​
​
  • 部署集群

    具体的部署可以参考文章 https://tidb.net/blog/af8080f7#TiDB- 最小实践Cluster111

# tiup cluster list
# tiup cluster stop cluster111
# tiup cluster destroy cluster111
​
# 部署cluster111集群
tiup cluster deploy cluster111 ./cluster111-full.yaml --user root -p
​
tiup cluster start cluster111

2.2 创建库表

CREATE DATABASE `b_crm` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ ;
​
drop table if exists `m_test_sort`;
CREATE TABLE `m_test_sort` (`id` int(11) NOT NULL AUTO_INCREMENT,`orgid` int(11) NOT NULL default 0,`labelid` int not null default 0,`catid` int not null default 0,`productid` int not null default 0,`p1` int not null default 0,`p2` int not null default 0,`p3` int not null default 0,`name` varchar(20) not null default '',`cust_id` char(30) not null default '', PRIMARY KEY (`id`) ,key ix_orgid(`orgid`),key ix_labelid_catid(`labelid`,`catid`),key ix_p1_p2_p3(`p1`,`p2`,`p3`),UNIQUE KEY uix_cust_id(`cust_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
​

2.3 表数据初始化

-- 插入1条 seed
insert into m_test_sort(orgid,labelid,catid,productid,p1,p2,p3,name,cust_id)values(1,1,1,1,1,1,1,'111','111');
​
-- 执行多次14次
insert into m_test_sort(orgid,labelid,catid,productid,p1,p2,p3,name,cust_id)
select  FLOOR(RAND() * 100),FLOOR(RAND() * 1000),FLOOR(RAND() * 100),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),FLOOR(RAND() * 1000),concat(substring('赵钱孙李周吴郑王冯陈诸卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢邹喻柏水窦章云苏潘葛奚范彭郎鲁韦昌马苗凤花方俞任袁柳酆鲍史唐费廉岑薛雷贺倪汤滕殷罗毕郝邬安常乐于时傅皮齐康伍余元卜顾孟平黄和穆萧尹姚邵堪汪祁毛禹狄米贝明臧计伏成戴谈宋茅庞熊纪舒屈项祝董粱杜阮蓝闵席季麻强贾路娄危江童颜郭梅盛林刁钟徐邱骆高夏蔡田樊胡凌霍虞万支柯咎管卢莫经房裘干解应宗丁宣贲邓郁单杭洪包诸左石崔吉钮龚',floor(1+190*rand()),1),substring('明国华建文平志伟东海强晓生光林小民永杰军金健一忠洪江福祥中正振勇耀春大宁亮宇兴宝少剑云学仁涛瑞飞鹏安亚泽世汉达卫利胜敏群波成荣新峰刚家龙德庆斌辉良玉俊立浩天宏子松克清长嘉红山贤阳乐锋智青跃元武广思雄锦威启昌铭维义宗英凯鸿森超坚旭政传康继翔栋仲权奇礼楠炜友年震鑫雷兵万星骏伦绍麟雨行才希彦兆贵源有景升惠臣慧开章润高佳虎根远力进泉茂毅富博霖顺信凡豪树和恩向道川彬柏磊敬书鸣芳培全炳基冠晖京欣廷哲保秋君劲轩帆若连勋祖锡吉崇钧田石奕发洲彪钢运伯满庭申湘皓承梓雪孟其潮冰怀鲁裕翰征谦航士尧标洁城寿枫革纯风化逸腾岳银鹤琳显焕来心凤睿勤延凌昊西羽百捷定琦圣佩麒虹如靖日咏会久昕黎桂玮燕可越彤雁孝宪萌颖艺夏桐月瑜沛诚夫声冬奎扬双坤镇楚水铁喜之迪泰方同滨邦先聪朝善非恒晋汝丹为晨乃秀岩辰洋然厚灿卓杨钰兰怡灵淇美琪亦晶舒菁真涵爽雅爱依静棋宜男蔚芝菲露娜珊雯淑曼萍珠诗璇琴素梅玲蕾艳紫珍丽仪梦倩伊茜妍碧芬儿岚婷菊妮媛莲娟一',floor(1+400*rand()),1),substring('明国华建文平志伟东海强晓生光林小民永杰军金健一忠洪江福祥中正振勇耀春大宁亮宇兴宝少剑云学仁涛瑞飞鹏安亚泽世汉达卫利胜敏群波成荣新峰刚家龙德庆斌辉良玉俊立浩天宏子松克清长嘉红山贤阳乐锋智青跃元武广思雄锦威启昌铭维义宗英凯鸿森超坚旭政传康继翔栋仲权奇礼楠炜友年震鑫雷兵万星骏伦绍麟雨行才希彦兆贵源有景升惠臣慧开章润高佳虎根远力进泉茂毅富博霖顺信凡豪树和恩向道川彬柏磊敬书鸣芳培全炳基冠晖京欣廷哲保秋君劲轩帆若连勋祖锡吉崇钧田石奕发洲彪钢运伯满庭申湘皓承梓雪孟其潮冰怀鲁裕翰征谦航士尧标洁城寿枫革纯风化逸腾岳银鹤琳显焕来心凤睿勤延凌昊西羽百捷定琦圣佩麒虹如靖日咏会久昕黎桂玮燕可越彤雁孝宪萌颖艺夏桐月瑜沛诚夫声冬奎扬双坤镇楚水铁喜之迪泰方同滨邦先聪朝善非恒晋汝丹为晨乃秀岩辰洋然厚灿卓杨钰兰怡灵淇美琪亦晶舒菁真涵爽雅爱依静棋宜男蔚芝菲露娜珊雯淑曼萍珠诗璇琴素梅玲蕾艳紫珍丽仪梦倩伊茜妍碧芬儿岚婷菊妮媛莲娟一',floor(1+400*rand()),if(rand()>0.6,0,1))),substring(md5(concat(rand(),rand(),rand(),rand())), 1, 30) from m_test_sort;
​
-- 16384 条记录
select count(*) from m_test_sort;
​

三、测试

主键忽略

-- 查找 最多的orgid
select orgid ,count(*) as ct from m_test_sort GROUP BY orgid ORDER BY ct desc limit 10;
​

3.1 二级索引 ix_orgid( orgid )

3.1.1 where:orgid,order:id

-- where:orgid索引;order:id索引读
EXPLAIN ANALYZE  select id from m_test_sort where orgid=8 order by id limit 100;

3.1.2 where:orgid,order:cust_id

-- where:orgid索引;order:回表 cust_id虽然是唯一索引但是还是回表
EXPLAIN ANALYZE  select id from m_test_sort where orgid=8 order by cust_id limit 100  ;

3.1.3 where:orgid,order:productid

-- where:orgid索引;order:回表  productid 没有索引
EXPLAIN ANALYZE select id from m_test_sort where orgid=8 order by productid limit 100 ;

3.1.4 where:orgid,order:catid

-- where:orgid索引;order:回表
EXPLAIN ANALYZE select id from m_test_sort where orgid=8 order by catid limit 100;

3.1.5 where:orgid,order:labelid

-- where:orgid索引;order:回表
EXPLAIN ANALYZE select id from m_test_sort where orgid=85 order by labelid  limit 100;

3.2 复合索引两列 ix_labelid_catid( labelid , catid )

-- 查询 最多的 labelid
select labelid ,count(*) as ct from m_test_sort GROUP BY labelid ORDER BY ct desc limit 10;

3.2.1 where:labelid,order:id

-- where:labelid索引,order:索引读
EXPLAIN ANALYZE select id from m_test_sort where labelid=962 order by id  limit 100;

3.2.2 where:labelid,order:catid

-- where:labelid索引,order:catid 走了复合索引的第二个字段
EXPLAIN ANALYZE select id from m_test_sort where labelid=962 order by catid  limit 100;

3.2.3 where:labelid,order:labelid

-- where:labelid索引,order:labelid 索引读
EXPLAIN ANALYZE select id from m_test_sort where labelid=962 order by labelid  limit 100;

3.2.4 where:labelid,order:cust_id

-- where:labelid索引,order:回表
EXPLAIN ANALYZE  select id from m_test_sort where labelid=962 order by cust_id limit 100  ;

3.2.5 where:labelid,order:productid

-- where:labelid索引,order:回表
EXPLAIN ANALYZE select id from m_test_sort where labelid=962 order by productid  limit 100;

3.2.6 where:labelid,order:orgid

-- where:labelid索引,order:回表
EXPLAIN ANALYZE select id from m_test_sort where labelid=962 order by orgid limit 100;

3.3复合索引三列 ix_p1_p2_p3( p1 , p2 , p3 )

-- 查找 最多的 labelid
select p1 ,count(*) as ct from m_test_sort GROUP BY p1 ORDER BY ct desc limit 10;

3.3.1 where:p1,order:id

-- where:p1索引,order:索引读
EXPLAIN ANALYZE select id from m_test_sort where p1=346 order by id  limit 100;

3.3.2 where:p1,order:p1

-- where:p1索引,order:索引读
EXPLAIN ANALYZE select id from m_test_sort where p1=346 order by p1  limit 100;

3.3.3 where:p1,order:p2

-- where:p1索引,order:索引读
EXPLAIN ANALYZE select id from m_test_sort where p1=346 order by p2  limit 100;

3.3.4 where:p1,order:p3

-- where:p1索引,order:索引读
EXPLAIN ANALYZE select id from m_test_sort where p1=346 order by p3  limit 100;

3.3.5 where:p1,p2,order:p3

-- where:p1,p2索引,order:索引读
EXPLAIN ANALYZE select id from m_test_sort where p1=346 and p2=32 order by p3  limit 100;

3.3.6 where:p1,order:labelid

-- where:p1索引,order:回表
EXPLAIN ANALYZE select id from m_test_sort where p1=346 order by labelid  limit 100;

3.3.7 where:p1,order:cust_id

-- where:p1索引,order:回表
EXPLAIN ANALYZE  select id from m_test_sort where p1=346 order by cust_id limit 100  ;

3.3.8 where:p1,order:productid

-- where:p1索引,order:回表
EXPLAIN ANALYZE select id from m_test_sort where p1=346 order by productid  limit 100;

3.3.9 where:p1,order:orgid

-- where:p1索引,order:回表
EXPLAIN ANALYZE select id from m_test_sort where p1=346 order by orgid limit 100;

3.3.10 where:p1,order:catid

-- where:p1索引,order:回表
EXPLAIN ANALYZE select id from m_test_sort where p1=346 order by catid  limit 100;

3.4 关于TopN 与limit

参考: https://docs.pingcap.com/zh/tidb/stable/topn-limit-push-down

Limit 节点等价于一个排序规则为空的 TopN 节点。

SQL 中的 LIMIT 子句在 TiDB 查询计划树中对应 Limit 算子节点,ORDER BY 子句在查询计划树中对应 Sort 算子节点,此外,我们会将相邻的 Limit 和 Sort 算子组合成 TopN 算子节点,表示按某个排序规则提取记录的前 N 项。从另一方面来说,Limit 节点等价于一个排序规则为空的 TopN 节点。

和谓词下推类似,TopN(及 Limit,下同)下推将查询计划树中的 TopN 计算尽可能下推到距离数据源最近的地方,以尽早完成数据的过滤,进而显著地减少数据传输或计算的开销。

四、总结

4.1 执行计划汇总

-- 查找 最多的orgid
select orgid ,count(*) as ct from m_test_sort GROUP BY orgid ORDER BY ct desc limit 10;
​
-- 二级索引
-- where:orgid索引;order:id索引读
EXPLAIN ANALYZE  select id from m_test_sort where orgid=8 order by id limit 100  ;
-- where:orgid索引;order:回表 cust_id虽然是唯一索引但是还是回表
EXPLAIN ANALYZE  select id from m_test_sort where orgid=8 order by cust_id limit 100  ;
-- where:orgid索引;order:回表  productid 没有索引
EXPLAIN ANALYZE select id from m_test_sort where orgid=8 order by productid limit 100 ;
-- where:orgid索引;order:回表
EXPLAIN ANALYZE select id from m_test_sort where orgid=8 order by catid limit 100;
-- where:orgid索引;order:回表
EXPLAIN ANALYZE select id from m_test_sort where orgid=85 order by labelid  limit 100;
​
​
​
---------------
-- 复合索引 2列复合
-- 查找 最多的 labelid
select labelid ,count(*) as ct from m_test_sort GROUP BY labelid ORDER BY ct desc limit 10;
-- where:labelid索引,order:索引读
EXPLAIN ANALYZE select id from m_test_sort where labelid=962 order by id  limit 100;
-- where:labelid索引,order:catid 走了复合索引的第二个字段
EXPLAIN ANALYZE select id from m_test_sort where labelid=962 order by catid  limit 100;
-- where:labelid索引,order:labelid 索引读
EXPLAIN ANALYZE select id from m_test_sort where labelid=962 order by labelid  limit 100;
-- where:labelid索引,order:回表
EXPLAIN ANALYZE  select id from m_test_sort where labelid=962 order by cust_id limit 100  ;
-- where:labelid索引,order:回表
EXPLAIN ANALYZE select id from m_test_sort where labelid=962 order by productid  limit 100;
-- where:labelid索引,order:回表
EXPLAIN ANALYZE select id from m_test_sort where labelid=962 order by orgid limit 100;
​
---------------
-- 复合索引 3列复合
-- 查找 最多的 labelid
select p1 ,count(*) as ct from m_test_sort GROUP BY p1 ORDER BY ct desc limit 10;
-- where:p1索引,order:索引读
EXPLAIN ANALYZE select id from m_test_sort where p1=346 order by id  limit 100;
-- where:p1索引,order:索引读
EXPLAIN ANALYZE select id from m_test_sort where p1=346 order by p1  limit 100;
-- where:p1索引,order:索引读
EXPLAIN ANALYZE select id from m_test_sort where p1=346 order by p2  limit 100;
-- where:p1索引,order:索引读
EXPLAIN ANALYZE select id from m_test_sort where p1=346 order by p3  limit 100;
-- where:p1,p2索引,order:索引读
EXPLAIN ANALYZE select id from m_test_sort where p1=346 and p2=32 order by p3  limit 100;
-- where:p1索引,order:回表
EXPLAIN ANALYZE select id from m_test_sort where p1=346 order by labelid  limit 100;
-- where:p1索引,order:回表
EXPLAIN ANALYZE  select id from m_test_sort where p1=346 order by cust_id limit 100  ;
-- where:p1索引,order:回表
EXPLAIN ANALYZE select id from m_test_sort where p1=346 order by productid  limit 100;
-- where:p1索引,order:回表
EXPLAIN ANALYZE select id from m_test_sort where p1=346 order by orgid limit 100;
-- where:p1索引,order:回表
EXPLAIN ANALYZE select id from m_test_sort where p1=346 order by catid  limit 100;
​

4.2 sql语句建议

  • where 条件尽量走索引
  • order by 尽量避免回表

谢谢 TiDB社区,谢谢TiDBer,后续会探索更多的TiDB相关的技术!

基于tidbV6.0探索索引优化思路相关推荐

  1. dataguru北京线下沙龙-第二部 《Oracle 索引优化思路--案例分享 -- 刘盛》

    [视频:dataguru北京线下沙龙-第二部 <Oracle 索引优化思路--案例分享 -- 刘盛> /微笑]

  2. 浅谈MySQL的B树索引与索引优化

    转载自   浅谈MySQL的B树索引与索引优化 MySQL的MyISAM.InnoDB引擎默认均使用B+树索引(查询时都显示为"BTREE"),本文讨论两个问题: 为什么MySQL ...

  3. 优化思路千万种,基于下界函数的最优化效率如何?

    作者丨stephenDC 来源 | 大数据与人工智能(ID:ai-big-data) 导读:生活中我们处处面临最优化的问题,比如,怎么样一个月减掉的体重最高?怎么样学习效率最高?怎么样可以最大化实现个 ...

  4. MySQL不走联合索引_mysql group by 多列优化思路?为什么不走联合索引?

    explain SELECT a, b, COUNT(*) FROM tbname GROUP BY a, b order by a DESC limit 1 a 和 b 列已经设置联合索引, 为什么 ...

  5. 袋鼠云数栈基于CBO在Spark SQL优化上的探索

    原文链接:袋鼠云数栈基于CBO在Spark SQL优化上的探索 一.Spark SQL CBO选型背景 Spark SQL的优化器有两种优化方式:一种是基于规则的优化方式(Rule-Based Opt ...

  6. 基于vue2.0实现音乐/视频播放进度条组件的思路及具体实现方法+代码解释

    基于vue2.0实现音乐/视频播放进度条组件的方法及代码解释 需求分析: ①:进度条随着歌曲的播放延长,歌曲播放完时长度等于黑色总进度条长度:时间实时更新. ②:当滑动按钮时,实时更新播放时间,橙色进 ...

  7. 数据结构-索引-实验7:索引优化(MySQL-8.0)

    文章目录 数据结构-索引-实验7:索引优化(MySQL-8.0) 一.实验目的及要求 二.实验环境及相关情况(包含使用软件.实验设备.主要仪器及材料等) 1.实验设备: 2.软件系统: 三.实验内容 ...

  8. sql查询索引语句_sql优化总结--基于sql语句优化和索引优化

    概述 最近做查询,统计和汇总.由于数据量比较庞大,大部分表数据上百万,甚至有的表数据上千万.所以在系统中做sql优化比较多,特此写一篇文章总结一下关于sql优化方面的经验. 导致查询缓慢的原因 1.数 ...

  9. 一种基于人工智能的化学合成机器人,用于纳米材料的探索和优化

    编辑 | 萝卜皮 格拉斯哥大学(University of Glasgow)的研究人员提出了一种自主化学合成机器人,用于探索.发现和优化由实时光谱反馈.理论和机器学习算法驱动的纳米结构,这些算法控制反 ...

  10. 飞浆AI studio人工智能课程学习(2)-Prompt优化思路|十个技巧高效优化Prompt|迭代法|Trick法|通用法|工具辅助

    文章目录 优化思路 上节课的例子 问题分析 思路解析 Prompt优化技巧 Prompt优化原理 十个技巧高效优化Prompt 迭代法 Trick法 工具法 通用技巧│定基础 通用技巧│做强调 需求强 ...

最新文章

  1. 应该知道关于Python的随机模型 以及使用范围例子洗牌 特别长 1米
  2. char* p = 123,字符串在内存中的哪个位置?
  3. Django环境的搭建以及最简示例
  4. Windows Server Backup 裸机恢复
  5. C语言接口的封装和设计专题
  6. HTML5语言格式,HTML5 自然语言格式的输入表单
  7. dependencies与devDependencies的区别
  8. airflow使用_使用AirFlow,SAS Viya和Docker像Pro一样自动化ML模型
  9. PS教程第十七课:放大看 缩小看
  10. 170504、MongoDB和MySQL对比(译)
  11. DDD-上下文映射图
  12. plsql导出文件转mysql_PLSQL Developer导入导出数据库
  13. 由一篇作文《一件有意义的事》展开的
  14. 微信文章编辑的html在哪里,微信公众号的文章编辑界面在哪里?怎么编辑排版? | 微信公众号指南...
  15. css+div透明参数设置
  16. c语言max函数是什么,什么是C语言函数
  17. 用QQ聊天记录生成一个词云
  18. let , const , var , 的区别
  19. 程序员应该了解的计算机知识(一)——基础理论
  20. 大数据高级开发工程师——Spark学习笔记(4)

热门文章

  1. StackMap属性解析
  2. 宁录哨兵机器人_能团灭X战警的哨兵机器人是漫威最强机器人吗?奥创:我不服!...
  3. Android ProfileOwner 应用的能力
  4. Yii2 常用操作总结
  5. android twitter第三方登录,android中接入twitter进行第三方登录
  6. GDPR 和个人信息保护的小知识
  7. 使用Zbar进行二维码识别 中文字符解码 RawBytes
  8. MongoDB分片式高可用集群搭建
  9. 分享两款雪花特效代码
  10. 如何卸载office201032位_企业如何利用Ansys Mechanical缩减设计时间、验证设计迭代?...