暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

基于tidbV6.0探索tiflash在多标签组合场景下的使用

边城元元 2022-05-16
197

作者:边城元元

原文来源:https://tidb.net/blog/3ca385cb

一、背景

1、有一个需求多字段表和几个基础信息表,现在的需求是需要对多字段表任意字段任意组合的查询。

2、考虑到对多个字段的不定组合进行筛选的话肯定要进行全表扫了。目前TiDBV6.0已经发布有一段时间了,TiFlash的性能也更加抢强大和稳定了,决定实验使用TiFlash来承接这部分的业务需求。

二、准备

2.1 建立TiDB cluster111

  • 拓扑如下(cluster111-full.yaml)

``` global: user: "tidb" ssh_port: 22 deploy_dir: "/tidb-deploy" data_dir: "/tidb-data" ​

# Monitored variables are applied to all the machines.

monitored: node_exporter_port: 9100 blackbox_exporter_port: 9115 ​ server_configs: tidb:   log.slow-threshold: 300   binlog.enable: false   binlog.ignore-error: false tikv:   readpool.storage.use-unified-pool: false   readpool.coprocessor.use-unified-pool: true pd:   schedule.leader-schedule-limit: 4   schedule.region-schedule-limit: 2048   schedule.replica-schedule-limit: 64   replication.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: 22   port: 20160   status_port: 20180   config:     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 ```

image.png

2.2 创建库表

CREATE TABLE `m_cust_org` (  `cust_id` char(30) not null,              `org_id` varchar(10) default null,          `org_name` varchar(100) default null,      `org_ii_id` varchar(10) default null,      `org_ii_name` varchar(100) default null,    `org_i_id` varchar(10) default null ,    `org_i_name` varchar(100) default null,    `org_level` varchar(2) default null ,                                                                            `pici` bigint(20) not null default '0',                                                                              PRIMARY KEY (`cust_id`) /*T![clustered_index] CLUSTERED */,  KEY `ix_m_cust_org_orgidmgrig` (`org_id`,`mgr_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='条件筛选表'; ​ ​ CREATE TABLE `m_cust_main` (  `cust_id` char(30) not null ,              `cust_name` varchar(200) default null,      `cert_type` varchar(13) default null,      `cert_num` varchar(40) default null ,      `cust_type` varchar(2) default null ,      `sex` varchar(13) default null,            `age` int(11) default null ,                `birth_dt` varchar(13) default null ,    `marriage` varchar(13) default null ,    `city_code` varchar(100) default null ,  `nation_code` varchar(100) default null ,                                                          `edu` varchar(13) default null ,          `ocup` varchar(100) default null ,        `post` varchar(20) default null ,        `copy_name` varchar(200) default null ,  `contact_addr` varchar(200) default null ,                                                          `card_level` varchar(2) default null ,    `service_level` varchar(2) default null ,                                                          `estimate_level` varchar(2) default null ,  `mark_id` varchar(50) default null ,      `mark_name` varchar(255) default null ,  primary key (`cust_id`) /*t![clustered_index] clustered */,  key `idx_m_cust_main_desc1` (`cert_type`,`cert_num`),  key `idx_m_cust_main_desc_3` (`cust_name`) ) engine=innodb default charset=utf8mb4 collate=utf8mb4_bin comment='客户主表'; ​ CREATE TABLE `m_cust_data` (  `cust_id` char(30) not null     ,            `asset` decimal(18,2) default null ,      `asset_mon_avg` decimal(18,2) default null ,  `asset_sea_avg` decimal(18,2) default null ,  `asset_yea_avg` decimal(18,2) default null ,  `asset_roll_avg` decimal(18,2) default null ,  `debt` decimal(18,2) default null ,      `dep_bal` decimal(18,2) default null ,    `dep_mon_avg` decimal(18,2) default null ,  `dep_sea_avg` decimal(18,2) default null ,  `dep_yea_avg` decimal(18,2) default null ,  `nd_bal` decimal(18,2) default null ,    `mf_bal` decimal(18,2) default null ,    `fund_bal` decimal(18,2) default null ,  `ccard_out_amt` decimal(18,2) default null ,  `ccard_bal` decimal(18,2) default null ,  `ins_bal` decimal(18,2) default null ,    `loan_bal` decimal(18,2) default null ,  `loan_amt` decimal(18,2) default null ,  `etl_date` char(8) default null ,        `qszg_bal` decimal(24,2) default null ,  `dx_fnc_bal` decimal(24,2) default null ,  `cur_dep_bal` decimal(18,2) default null ,  `rep_bal` decimal(18,2) default null ,    `rep_avg` decimal(18,2) default null ,    `is_rep_beyond` char(2) default null ,  Primary Key (`cust_id`) /*t![clustered_index] clustered */,  Key `idx_m_cust_query_desc_4` (`asset_sea_avg`,`cust_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='客户频繁更新数据表'; ​ ​ CREATE TABLE `m_cust_label` (  `cust_id` char(30) NOT NULL,                    `cat1` int not null default  0 ,               `cat2` int not null default  0 ,                 `cat3` int not null default  0 ,                 `cat4` int not null default  0 ,                 `cat5` int not null default  0 ,                 `cat6` int not null default  0 ,                 `cat7` int not null default  0 ,                 `cat8` int not null default  0 ,                 `cat9` int not null default  0 ,                 `cat10` int not null default  0 ,               `cat11` int not null default  0 ,               `cat12` int not null default  0 ,               `cat13` int not null default  0 ,               `cat14` int not null default  0 ,               `cat15` int not null default  0 ,               `cat16` int not null default  0 ,               `cat17` int not null default  0 ,               `cat18` int not null default  0 ,               `cat19` int not null default  0 ,               `cat20` int not null default  0 ,               `cat21` int not null default  0 ,               `cat22` int not null default  0 ,               `cat23` int not null default  0 ,               `cat24` int not null default  0 ,               `cat25` int not null default  0 ,               `cat26` int not null default  0 ,               `cat27` int not null default  0 ,               `cat28` int not null default  0 ,               `cat29` int not null default  0 ,               `cat30` int not null default  0 ,               `cat31` int not null default  0 ,               `cat32` int not null default  0 ,               `cat33` int not null default  0 ,               `cat34` int not null default  0 ,               `cat35` int not null default  0 ,               `cat36` int not null default  0 ,               `cat37` int not null default  0 ,               `cat38` int not null default  0 ,               `cat39` int not null default  0 ,               `cat40` int not null default  0 ,               `cat41` int not null default  0 ,               `cat42` int not null default  0 ,               `cat43` int not null default  0 ,               `cat44` int not null default  0 ,               `cat45` int not null default  0 ,               `cat46` int not null default  0 ,               `cat47` int not null default  0 ,               `cat48` int not null default  0 ,               `cat49` int not null default  0 ,               `cat50` int not null default  0 ,               `cat51` int not null default  0 ,               `cat52` int not null default  0 ,               `cat53` int not null default  0 ,               `cat54` int not null default  0 ,               `cat55` int not null default  0 ,               `cat56` int not null default  0 ,               `cat57` int not null default  0 ,               `cat58` int not null default  0 ,               `cat59` int not null default  0 ,               `cat60` int not null default  0 ,               `cat61` int not null default  0 ,               `cat62` int not null default  0 ,               `cat63` int not null default  0 ,               `cat64` int not null default  0 ,               `cat65` int not null default  0 ,               `cat66` int not null default  0 ,               `cat67` int not null default  0 ,               `cat68` int not null default  0 ,               `cat69` int not null default  0 ,                       PRIMARY KEY (`CUST_ID`) /*T![clustered_index] CLUSTERED */ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='客户检索标签'; ​

image.png

2.3 初始化数据种子表

-- 建立seed -- m_seed drop table if exists `m_seed`; CREATE TABLE `m_seed` (  `id` int(11) NOT NULL AUTO_INCREMENT,  PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; ​ truncate table m_seed; SELECT * from m_seed; ​ ​ insert into m_seed values(); -- 不连续的id 每次 【执行完后,auto_inccreaid 造成不连续】 insert into m_seed select null from m_seed; insert into m_seed select null from m_seed; insert into m_seed select null from m_seed; insert into m_seed select null from m_seed; insert into m_seed select null from m_seed; insert into m_seed select null from m_seed; ​ -- 本地虚拟机环境配置比较低这里使用每次528条记录 -- 528 SELECT count(*) from m_seed;

2.4 初始化数据脚本bat版

``` ::echo off @echo off

​ rem 每次的数量为 m_seed表中的记录数 rem 总次数 set/a sumnum=200 set num=0 ​ rem 这里必须有 start标签,否则循环里去时间 (都一样 的时间,需要从新调度) rem 在bat里有中文的,需要设置为gb2312的编码,,到sql才是中文 :start set pici=%Date:~5,2%%Date:~8,2%%Time:~0,2%%Time:~3,2%%Time:~6,2% set pici=%pici: =% echo %pici% ​

​ echo '----------------1-----------' mysql -h 127.0.0.1 -P 4000 -u "root" -D b_crm -e "INSERT INTO b_crm.m_cust_org(CUST_ID, ORG_ID, ORG_NAME, ORG_II_ID, ORG_II_NAME, ORG_I_ID, ORG_I_NAME, ORG_LEVEL, pici) select concat('%pici%','A',id), FLOOR( 100 + RAND() * (10000 - 100)),concat('归属三级机构名称', RAND() ), FLOOR( 100 + RAND() * (10000 - 100)),concat('归属二级机构名称', RAND() ), FLOOR( 100 + RAND() * (10000 - 100)),concat('归属一级机构名称', RAND() ), FLOOR( 1 + RAND() * (10 - 1)),'%pici%' from m_seed " --default-character-set=utf8 ​ echo '----------------2-----------' rem 2 mysql -h 127.0.0.1 -P 4000 -u "root" -D b_crm -e "INSERT INTO m_cust_data(CUST_ID, ASSET, ASSET_MON_AVG, ASSET_SEA_AVG, ASSET_YEA_AVG, ASSET_ROLL_AVG, DEBT, DEP_BAL, DEP_MON_AVG, DEP_SEA_AVG, DEP_YEA_AVG, ND_BAL, MF_BAL, FUND_BAL, CCARD_OUT_AMT, CCARD_BAL, INS_BAL, LOAN_BAL, LOAN_AMT, ETL_DATE, QSZG_BAL, DX_FNC_BAL, CUR_DEP_BAL, REP_BAL, REP_AVG, IS_REP_BEYOND) select concat('%pici%','A',id) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) , FLOOR(RAND() 100000000) ,DATE_FORMAT(FROM_UNIXTIME(1524895617+FLOOR(RAND() * 126230510)),'%%Y%%m%%d') , FLOOR(RAND() 10000000) , FLOOR(RAND() 10000000) , FLOOR(RAND() 10000000) , FLOOR(RAND() 10000000) , FLOOR(RAND() *10000000) , if(RAND() >0.9,'Y','N') from m_seed " --default-character-set=utf8

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


echo '----------------4-----------' 
mysql -h 127.0.0.1 -P 4000 -u "root"  -D b_crm -e "INSERT INTO m_cust_label(CUST_ID,cat1,cat2,cat3,cat4,cat5,cat6,cat7,cat8,cat9,cat10) select  concat('%pici%','A',id) , FLOOR(RAND() *1000),FLOOR(RAND() *1000),FLOOR(RAND() *100),FLOOR(RAND() *100),FLOOR(RAND() *10),FLOOR(RAND() *10),FLOOR(RAND() *800),FLOOR(RAND() *700),FLOOR(RAND() *600),FLOOR(RAND() *100000) from m_seed "

​ rem 数值的相加 set/a num= %num%+1 echo %num% echo %sumnum% rem 比较大小 geq 表示大于等于 rem 注意小括号 if %num% geq %sumnum% ( echo '--------------------------' echo %sumnum% echo '---------end--------------' goto stop )

timeout /T 5 /NOBREAK

goto start

​ :stop echo '---stop ----' ​ ​ pause ```

三、测试多字段组合

3.1 准备数据

3.1.1 准备c1,c2,... c10 中找出数量排行前5的作为测试数据使用

-- cat1   516 select a1.* from (select 'c1',cat1,count(*) as ct  from m_cust_label GROUP BY cat1 ORDER BY ct desc limit 5 ) a1 union all select a2.* from (select 'c2',cat2,count(*) as ct  from m_cust_label GROUP BY cat2 ORDER BY ct desc limit 5) a2 union all select a3.* from (select 'c3',cat3,count(*) as ct  from m_cust_label GROUP BY cat3 ORDER BY ct desc limit 5 ) a3 union all select a4.* from (select 'c4',cat4,count(*) as ct  from m_cust_label GROUP BY cat4 ORDER BY ct desc limit 5 ) a4 union all select a5.* from (select 'c5',cat5,count(*) as ct  from m_cust_label GROUP BY cat5 ORDER BY ct desc limit 5 ) a5 union all select a6.* from (select 'c6',cat6,count(*) as ct  from m_cust_label GROUP BY cat6 ORDER BY ct desc limit 5 ) a6 union all select a7.* from (select 'c7',cat7,count(*) as ct  from m_cust_label GROUP BY cat7 ORDER BY ct desc limit 5 ) a7 union all select a8.* from (select 'c8',cat8,count(*) as ct  from m_cust_label GROUP BY cat8 ORDER BY ct desc limit 5 ) a8 union all select a9.* from (select 'c9',cat9,count(*) as ct  from m_cust_label GROUP BY cat9 ORDER BY ct desc limit 5 ) a9 union all select a10.* from (select 'c10',cat10,count(*) as ct  from m_cust_label GROUP BY cat10 ORDER BY ct desc limit 5) a10; ​

cat字段,id值,记录条数 c3 19 155 c3 37 153 c3 45 153 c3 66 151 c3 50 151 ​ c2 154 25 c2 937 25 c2 203 24 c2 82 23 c2 504 22 ​ c5 7 1353 c5 1 1305 c5 4 1298 c5 3 1268 c5 8 1267 ​ c4 99 159 c4 65 150 c4 47 150 c4 8 149 c4 46 148 ​ c1 516 26 c1 710 26 c1 121 25 c1 230 25 c1 889 25 ​ c6 0 1343 c6 9 1303 c6 7 1291 c6 6 1288 c6 8 1287 ​ c7 196 30 c7 751 29 c7 756 27 c7 584 27 c7 265 26 ​ c8 27 36 c8 239 33 c8 604 31 c8 214 30 c8 126 30 ​ c9 416 39 c9 38 37 c9 69 36 c9 91 35 c9 72 35 ​ c10 94038 3 c10 46313 3 c10 72580 3 c10 92499 3 c10 94648 3

3.1.2 准备orgid

select ORG_ID,count(*) as ct from m_cust_org GROUP BY ORG_ID ORDER BY ct desc limit 10;

image.png

3.1.3 开启TiFlash

``` -- 针对指定表开启 Tiflash(列存) ALTER TABLE m_cust_label SET TIFLASH REPLICA 1;

-- 查看TiFlash同步状态 select * from information_schema.tiflash_replica; select * from information_schema.TIFLASH_SEGMENTS; select * from information_schema.TIFLASH_TABLES; ```

image.png

progress=1 表示同步完成!

3.2 具体场景分析

3.2.1 仅有宽表m_cust_label字段的组合

思路:先找出主键,在组装其他需要字段

``` EXPLAIN ANALYZE select a.,b.CUST_NAME, b.CERT_TYPE, b.CERT_NUM, b.CUST_TYPE, b.SEX, b.AGE, b.BIRTH_DT,c.ORG_ID, c.ORG_NAME,d.ASSET,d.ASSET_MON_AVG from( -- 思路找到cust_id select /+ read_from_storage(tiflash[m]) */ m.cust_id from m_cust_label m where m.cat1 in(516,710,230) and m.cat2 in(154,504) ORDER BY m.cust_id desc limit 100

) a left join m_cust_main b on a.cust_id=b.cust_id left join m_cust_org c on a.cust_id=c.cust_id left join m_cust_data d on a.cust_id=d.cust_id; ```

image.png

指定使用了Tiflash的列扫,

如果不指定Tiflash而是指定TikV又是什么情况呢?

``` EXPLAIN ANALYZE select a.,b.CUST_NAME, b.CERT_TYPE, b.CERT_NUM, b.CUST_TYPE, b.SEX, b.AGE, b.BIRTH_DT,c.ORG_ID, c.ORG_NAME,d.ASSET,d.ASSET_MON_AVG from( -- 思路找到cust_id select /+ read_from_storage(tikv[m]) */ m.cust_id from m_cust_label m where m.cat1 in(516,710,230) and m.cat2 in(154,504) ORDER BY m.cust_id desc limit 100

) a left join m_cust_main b on a.cust_id=b.cust_id left join m_cust_org c on a.cust_id=c.cust_id left join m_cust_data d on a.cust_id=d.cust_id; ```

image.png

在不确定组合的情况下无法使tikv加索引如果数据量较大的话tiflash的列扫更优有事。

3.2.2 仅有同表非宽表字段

``` EXPLAIN ANALYZE select a.*,b.CUST_NAME, b.CERT_TYPE, b.CERT_NUM, b.CUST_TYPE, b.SEX, b.AGE, b.BIRTH_DT,c.ORG_ID, c.ORG_NAME,d.ASSET,d.ASSET_MON_AVG from( -- 思路找到cust_id select n.cust_id from m_cust_org n where n.ORG_ID in('8716','7162') ORDER BY n.cust_id desc limit 100

) a left join m_cust_main b on a.cust_id=b.cust_id left join m_cust_org c on a.cust_id=c.cust_id left join m_cust_data d on a.cust_id=d.cust_id; ```

image.png

3.2.3 异表包含宽表字段

``` EXPLAIN ANALYZE select a.,b.CUST_NAME, b.CERT_TYPE, b.CERT_NUM, b.CUST_TYPE, b.SEX, b.AGE, b.BIRTH_DT,c.ORG_ID, c.ORG_NAME,d.ASSET,d.ASSET_MON_AVG from( -- 思路找到cust_id select /+ read_from_storage(tiflash[m]) */ m.cust_id from m_cust_label m right join m_cust_org n on m.CUST_ID=n.CUST_ID where m.cat1 in(516,710,230) and n.ORG_ID in('8716','7162') ORDER BY m.cust_id desc limit 100

) a left join m_cust_main b on a.cust_id=b.cust_id left join m_cust_org c on a.cust_id=c.cust_id left join m_cust_data d on a.cust_id=d.cust_id ```

image.png

利用了Tiflash的列扫和Tikv的索引优势。

3.2.4 异表不包含宽表字段

``` -- 1、先查cust_id的方式 EXPLAIN ANALYZE select a.*,b.CUST_NAME, b.CERT_TYPE, b.CERT_NUM, b.CUST_TYPE, b.SEX, b.AGE, b.BIRTH_DT,c.ORG_ID, c.ORG_NAME,d.ASSET,d.ASSET_MON_AVG from( -- 思路找到cust_id select m.cust_id from m_cust_data m right join m_cust_org n on m.CUST_ID=n.CUST_ID where m.ASSET BETWEEN 10 and 100 and n.ORG_ID in('8716','7162') ORDER BY m.cust_id desc limit 100

) a left join m_cust_main b on a.cust_id=b.cust_id left join m_cust_org c on a.cust_id=c.cust_id left join m_cust_data d on a.cust_id=d.cust_id ```

image.png

-- 2、直接join的方式 EXPLAIN ANALYZE select b.cust_id,b.CUST_NAME, b.CERT_TYPE, b.CERT_NUM, b.CUST_TYPE, b.SEX, b.AGE, b.BIRTH_DT,c.ORG_ID, c.ORG_NAME,d.ASSET,d.ASSET_MON_AVG from m_cust_main b left join m_cust_org c on b.cust_id=c.cust_id left join m_cust_data d on b.cust_id=d.cust_id where d.asset BETWEEN 10 and 100 and c.ORG_ID in('8716','7162') ORDER BY b.cust_id desc limit 100

image.png

在测试环境中这2个的速度差不多,从执行计划来看的话 先查cust_id的效率高一些!

3.3 Tiflash的优化

既然要使用TiFlash来承接宽表的检索 那么如何优化TiFlash呢。

  • 1、TiFlash的副本最好大于1小于TiKV的数量

  • 2、TiFlash的并发数

适当调大tidb_distsql_scan_concurrency增大并发度

  • 3、TiFlash节点要独立部署

四、总结

基本思路:1)建立了聚簇表 ;2)使用where过滤数据保留尽可能晓的数据记录;3)先找主键再join

对于不确定字段组合的情况可以参考下面

  • 1、不确定where条件列和order排序列 必定会走全表扫tableFullScan 使用tiflash来加速不确定条件的筛选
  • 2、where,order,limit 只是筛选出主键, 根据主键再join出需要的字段。
  • 3、不走tiflash的字段,可以考虑走tikv的索引

非常感谢TiDB社区的提供学习交流的机会!

期待TiDB 6.0长期支持版本 发布!

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论