针对于优化器在索引存在时依然使⽤全表扫描的情况下,使⽤缓存表和分区表是提升查询性能的有效⼿段。

缓存表

  • 缓存表是将表的内容完全缓存到 TiDB Server 的内存中
  • 表的数据量不⼤,⼏乎不更改
  • 读取很频繁
  • 缓存控制: ALTER TABLE table_name CACHE|NOCACHE;
# 使用trace跟踪下
tidb> TRACE SELECT * FROM test.c1;
+-------------------------------------------+-----------------+---
---------+
| operation | startTS |
duration |
+-------------------------------------------+-----------------+---
---------+
| trace | 18:39:25.485266 |
501.582µs |
| ├─session.ExecuteStmt | 18:39:25.485270 |
432.208µs |
| │ ├─executor.Compile | 18:39:25.485281 |
132.616µs |
| │ └─session.runStmt | 18:39:25.485433 |
249.488µs |
| │ └─UnionScanExec.Open | 18:39:25.485572 |
72.776µs |
| │ ├─TableReaderExecutor.Open | 18:39:25.485575 |
13.24µs |
| │ ├─buildMemTableReader | 18:39:25.485605 |
3.283µs |
| │ └─memTableReader.getMemRows | 18:39:25.485615 | # memTableReader.getMemRows 表示从缓存取数
20.558µs |
| ├─*executor.ProjectionExec.Next | 18:39:25.485712 |
12.911µs |
| │ └─*executor.UnionScanExec.Next | 18:39:25.485714 |
3.823µs |
| └─*executor.ProjectionExec.Next | 18:39:25.485733 |
8.943µs |
| └─*executor.UnionScanExec.Next | 18:39:25.485735 |
1.33µs |
+-------------------------------------------+-----------------+---
---------+
12 rows in set (0.00 sec)

小表缓存-原理

缓存租约

  • 租约时间内,无法进行写操作

  • 租约到期,数据过期

  • 写操作不再被阻塞

  • 读写直接到TiKV节点上执行

  • 数据更新完毕,租约继续开启

应用场景

  • 每张缓存表的大小限制为64MB
  • 适用于查询频繁、数据量不大、修改极少的场景
  • 在租约(tidb_table_cache_lease) 时间内,写操作会被阻塞
  • 当租约到期(tidb_table_cache_lease)时,读性能会下降
  • 不支持对缓存表直接做DDL操作,需要先关闭
  • 对于表加载较慢或者极少修改的表,可以适当延长tidb_table_cache_lease保持读性能稳定

分区表

分区类型与适用场景

  • range: 分区剪裁,节省IO开销
  • Hash: 用于大规模写入的情况下将数据打散,平均地分配到各个分区里
Range分区表
create table t1(x int) partition by name(x) (
partition p0 values less than(5),
partition p1 values less than (10));
)

分区类型与适⽤场景

  • Range

分区裁剪, 节省 I/O 开销

/* Range Partition t1 */
drop table if exists test.t1;
create table test.t1 (x int) partition by range (x) (
partition p0 values less than (5),
partition p1 values less than (10));
insert into test.t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
insert into test.t1 select * from test.t1;
/* Check Partition Pruning */
explain select * from test.t1 where x between 1 and 4;
查看执行计划
mysql> explain select * from test.t1 where x between 1 and 4;
+-------------------------+-----------+-----------+------------------------+------------------------------------+
| id | estRows | task | access object | operator info |
+-------------------------+-----------+-----------+------------------------+------------------------------------+
| TableReader_9 | 12288.00 | root | | data:Selection_8 |
| └─Selection_8 | 12288.00 | cop[tikv] | | ge(test.t1.x, 1), le(test.t1.x, 4) |
| └─TableFullScan_7 | 491520.00 | cop[tikv] | table:t1, partition:p0 | keep order:false |
+-------------------------+-----------+-----------+------------------------+------------------------------------+
3 rows in set (0.03 sec)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
/* Check regions */
show table test.t1 regions;
mysql> show table test.t1 regions;
+-----------+-----------+---------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
| REGION_ID | START_KEY | END_KEY | LEADER_ID | LEADER_STORE_ID | PEERS | SCATTERING | WRITTEN_BYTES | READ_BYTES | APPROXIMATE_SIZE(MB) | APPROXIMATE_KEYS |
+-----------+-----------+---------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
| 5019 | t_79_ | t_80_ | 5020 | 1001 | 5020 | 0 | 0 | 0 | 67 | 877551 |
| 1002 | t_80_ | | 1003 | 1001 | 1003 | 0 | 0 | 0 | 24 | 421921 |
+-----------+-----------+---------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
2 rows in set (0.02 sec)
  • Hash

可以⽤于⼤规模写⼊的情况下将数据打散, 平均地分配到各个分区⾥

/* Hash Partition t1 */
drop table if exists test.t1;
CREATE TABLE test.t1 (x INT)
PARTITION BY HASH(x)
PARTITIONS 4; insert into test.t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

insert into test.t1 select * from test.t1;

查看分区的执行计划

  • 默认是通过mod方式分配分区
/* Check Partition Distribution */

explain select  from test.t1 where x=0;

explain select
from test.t1 where x=1;

explain select from test.t1 where x=2;

explain select
from test.t1 where x=3;

explain select from test.t1 where x=4;

explain select
from test.t1 where x=5;

explain select from test.t1 where x=6;

explain select
from test.t1 where x=7;

explain select from test.t1 where x=8;

explain select
from test.t1 where x=9;

/* Negative /

explain select
from test.t1 where x between 7 and 9;

mysql> explain select * from test.t1 where x between 7 and 9;

+------------------------------+----------+-----------+------------------------+------------------------------------+

| id | estRows | task | access object | operator info |

+------------------------------+----------+-----------+------------------------+------------------------------------+

| PartitionUnion_10 | 750.00 | root | | |

| ├─TableReader_13 | 250.00 | root | | data:Selection_12 |

| │ └─Selection_12 | 250.00 | cop[tikv] | | ge(test.t1.x, 7), le(test.t1.x, 9) |

| │ └─TableFullScan_11 | 10000.00 | cop[tikv] | table:t1, partition:p0 | keep order:false, stats:pseudo |

| ├─TableReader_16 | 250.00 | root | | data:Selection_15 |

| │ └─Selection_15 | 250.00 | cop[tikv] | | ge(test.t1.x, 7), le(test.t1.x, 9) |

| │ └─TableFullScan_14 | 10000.00 | cop[tikv] | table:t1, partition:p1 | keep order:false, stats:pseudo |

| └─TableReader_19 | 250.00 | root | | data:Selection_18 |

| └─Selection_18 | 250.00 | cop[tikv] | | ge(test.t1.x, 7), le(test.t1.x, 9) |

| └─TableFullScan_17 | 10000.00 | cop[tikv] | table:t1, partition:p3 | keep order:false, stats:pseudo |

+------------------------------+----------+-----------+------------------------+------------------------------------+

10 rows in set (12.69 sec)

查看region分布情况

/* Check regions */
# 查看对应的region情况,在4个region上
mysql> show table test.t1 regions;
+-----------+-----------+---------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
| REGION_ID | START_KEY | END_KEY | LEADER_ID | LEADER_STORE_ID | PEERS | SCATTERING | WRITTEN_BYTES | READ_BYTES | APPROXIMATE_SIZE(MB) | APPROXIMATE_KEYS |
+-----------+-----------+---------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
| 9003 | t_84_ | t_85_ | 9004 | 1001 | 9004 | 0 | 18449249 | 14117466 | 13 | 141205 |
| 9005 | t_85_ | t_86_ | 9006 | 1001 | 9006 | 0 | 18443067 | 14024508 | 10 | 58475 |
| 9007 | t_86_ | t_87_ | 9008 | 1001 | 9008 | 0 | 12295360 | 8703102 | 5 | 27228 |
| 1002 | t_87_ | | 1003 | 1001 | 1003 | 0 | 12295959 | 9218671 | 4 | 26666 |
+-----------+-----------+---------+-----------+-----------------+-------+------------+---------------+------------+----------------------+------------------+
4 rows in set (2 min 46.43 sec)

[转帖]043、TiDB特性_缓存表和分区表的更多相关文章

  1. (转载)详解网络传输中的三张表,MAC地址表、ARP缓存表以及路由表

    郑重声明:原文转载于http://dengqi.blog.51cto.com/5685776/1223132 向好文章致敬!!! 一:MAC地址表详解 说到MAC地址表,就不得不说一下交换机的工作原理 ...

  2. Spring4.1新特性——Spring缓存框架增强(转)

    目录 Spring4.1新特性——综述 Spring4.1新特性——Spring核心部分及其他 Spring4.1新特性——Spring缓存框架增强 Spring4.1新特性——异步调用和事件机制的异 ...

  3. ARP缓存表的构成ARP协议全面实战协议详解、攻击与防御

    ARP缓存表的构成ARP协议全面实战协议详解.攻击与防御 1.4.3  ARP缓存表的构成 在局域网的任何一台主机中,都有一个ARP缓存表.该缓存表中保存中多个ARP条目.每个ARP条目都是由一个IP ...

  4. Oracle11g新特性导致空表不能导出问题

        ORACLE 11G在用EXP导出时,发现空表(没有数据或者没有用过的表)不能导出了.     查了一下资料,说是Oracle 11G中有个新特性,当表无数据时,不分配segment,以节省空 ...

  5. 关于我们_ | 腕表时代watchtimes.com.cn

    关于我们_ | 腕表时代watchtimes.com.cn 关于我们         腕表时代是北京兰会时光科技有限公司旗下运营的手表网站.腕表时代于2013年5月17日正式上线.秉承专业.生动.实用 ...

  6. 网络传输中的三张表,MAC地址表、ARP缓存表以及路由表

    一:MAC地址表详解 说到MAC地址表,就不得不说一下交换机的工作原理了,因为交换机是根据MAC地址表转发数据帧的.在交换机中有一张记录着局域网主机MAC地址与交换机接口的对应关系的表,交换机就是根据 ...

  7. SQL基本查询_单表查询(实验二)

    SQL基本查询_单表查询(实验二) 查询目标表结构及数据 emp empno ename job hiedate sal comn deptno 1007 马明 内勤 1992-6-12 4000 2 ...

  8. SQL基本查询_多表查询(实验三)

    SQL基本查询_多表查询(实验三) 题目要求(一) 针对emp.dept两表完成如下查询,并验证查询结果的正确性 使用显式内连接查询所有员工的信息,显示其编号.姓名.薪水.入职日期及部门名称: 使用隐 ...

  9. SQL Server 表的管理_关于表的操作增删查改的操作的详解(案例代码)

    SQL Server 表的管理_关于表的操作增删查改的操作的详解(案例代码) 概述: 表由行和列组成,每个表都必须有个表名. SQL CREATE TABLE 语法 CREATE TABLE tabl ...

  10. 缓存表 内存表(将表keep到内存)

    缓存表 内存表(将表keep到内存) 一.引言:     有时候一些基础表需要非常的频繁访问,尤其是在一些循环中,对该表中的访问速度将变的非常重要.为了提高系统的处理性能,可以考虑将一些表及索引读取并 ...

随机推荐

  1. Ubuntu搭建邮件服务器

    转载:原文链接 前言 关于邮件服务器的工作原理我就不再赘述了.Postfix是优秀的MTA,而Dovecot则是优秀的MDA.前者负责发信.收信,提供smtp服务:后者负责邮件保存到邮箱,提供pop3 ...

  2. k8s在删除pod时优雅关闭sigterm信号传输失败

    背景 随着云原生技术的流行,越来越多的应用选择容器化,容器化的话题自然离不开 Kubernetes .Pod 是 Kubernetes 中创建和管理的.最小的可部署的计算单元,一个 Pod 中有多个容 ...

  3. 让gorm代码飞起来,gorm+gmodeltool生成entity,让实体类代码更轻松。

    背景 不卷!php经历多年的不衰败的原因只有一个,哪就是不卷,但是由于并发和缺乏编译严谨度降低,使得长青树不得己走向了衰败. 但!叱咤风云多年,大企百度.腾讯.新浪.搜狐的首先语言的流行在于,其语言的 ...

  4. 从部署和运维说说DLI(1)

    DLI是支持多模引擎的Serverless大数据计算服务,其很好的实现了Serverless的特性:   1. 弱化了存储和计算之间的联系: 2. 代码的执行不再需要手动分配资源: 3. 按使用量计费 ...

  5. 窗口到底有多滑动?揭秘TCP/IP滑动窗口的工作原理

    本文分享自华为云社区<窗口到底有多滑动?揭秘TCP/IP滑动窗口的工作原理>,作者: Lion Long. 当涉及网络性能优化和数据传输可靠性时,TCP/IP滑动窗口是一个关键的技术.本文 ...

  6. 抖音APP如何实现用户生命周期提升

    > 更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 近日,在火山引擎数智平台在北京举办的"超话数据:企业产品优化分享"的活动上,抖音策略 ...

  7. 火山引擎 DataTester 揭秘:字节如何用 A/B 测试,解决增长问题的?

      更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 上线六年,字节跳动的短视频产品--抖音已成为许多人记录美好生活的平台.除了抖音,字节跳动旗下还同时运营着数十款 ...

  8. Solon2 之基础:四、应用启动过程与完整生命周期

    串行的处理过程(含六个事件扩展点 + 两个函数扩展点),代码直接.没有什么模式.易明 提醒: 启动过程完成后,项目才能正常运行(启动过程中,不能把线程卡死了) AppBeanLoadEndEvent ...

  9. Axure 安装使用 FontAwesome

    Axure 安装使用 FontAwesome. 字体下载:https://www.bootcss.com/p/font-awesome/ 解压后,到 font 目录,双击 FontAwesome.ot ...

  10. 简洁好用的python-pip包更新工具

    今天推荐一个github的开源工具 pkgu,支持以表格形式展示当前python环境下的有新版本的package的版本信息,并支持全部或部分更新这些已经过期或者有新版的库. 该工具目前还提供了 cac ...