【GreatSQL 优化器 - 01】const_table

news/2024/11/8 21:05:09/文章来源:https://www.cnblogs.com/XX-SHE/p/18535918

一、const_table 介绍
GreatSQL 的优化器主要用 JOIN 类来进行处理 SQL 语句的,JOIN 类有以下四个 table 数量相关的成员变量。其中 const_tables 是 optimize 最开始就检查并且标识的,因为这样可以把记录最少的表放在执行计划的第一步,在后面的执行计划里面这些 const tables 是不参与循环遍历和计算的,因此可以减少很多开销。

计数名称 说明 哪个函数进行累加
tables 该查询语句的所有表的数量,包含物化表和临时表 JOIN::get_best_combination()
primary_tables 该查询语句的主要表的数量,不包含物化表 JOIN::get_best_combination()
const_tables 该查询语句中只有 0 行或者 1 行的表数量 JOIN::extract_const_tables 和 JOIN::extract_func_dependent_tables
tmp_tables 该查询语句中临时表数量 JOIN::make_tmp_tables_info()
下面用一个简单的例子来说明 const_table 是什么。

greatsql> CREATE TABLE t1 (c1 int primary key, c2 varchar(32),date1 datetime);
greatsql> INSERT INTO t1 VALUES (1,'aaa','2021-03-25 16:44:00.123456'),(2,'bbb','2022-03-25 16:44:00.123456'),(3,'ccc','2023-03-25 16:44:00.123456');

这里看到以下的type类型是const,说明在优化器看来这是一张const table

greatsql> EXPLAIN SELECT * FROM t1 WHERE c1=1 AND c1<10;
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| 1 | SIMPLE | t1 | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | NULL |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (3.60 sec)

这句sql语句最后被处理成以下的语句了,可以看到条件语句被提到前面当做列,最后的条件变为where true了。

greatsql> SHOW WARNINGS;
+-------+------+-------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+-------------------------------------------------------------------------------------------------------------+
| Note | 1003 | /* select#1 */ select '1' AS c1,'aaa' AS c2,'2021-03-25 16:44:00' AS date1 from db1.t1 where true |
+-------+------+-------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
二、const_table 标识
const_table 的寻找和标识在函数 JOIN::extract_const_tables 和 JOIN::extract_func_dependent_tables 进行处理,这两个函数的功能各有不同。用上面的例子来说明。

bool JOIN::make_join_plan() {
if (!(query_block->active_options() & OPTION_NO_CONST_TABLES)) {
// Detect tables that are const (0 or 1 row) and read their contents.
//根据表的统计信息table->file->stats.records直接寻找该值为0或者1的表,并且表的cached_table_flags必须为HA_STATS_RECORDS_IS_EXACT,只有引擎是MyISAM和memory才有这个标志
if (extract_const_tables()) return true;

// Detect tables that are functionally dependent on const values.
// 循环所有剩下的没有被标识的表,找出有索引或者有表依赖的表来标识
if (extract_func_dependent_tables()) return true;

}
}

bool JOIN::extract_func_dependent_tables() {
do {
for (JOIN_TAB **pos = best_ref + const_tables; *pos; pos++) {
一、遍历每张出现的表,寻找表里已经创建的索引。
二、判断表有join条件的情况,本次不涉及
三、判断表有表依赖的情况,本次不涉及
四、检查表是否可以通过key读取或表仅使用 const ref。
这里需要排除以下表:
1. 全文搜索,或
2. 嵌套外连接的一部分,或
3. 半连接的一部分,或
4. 具有大开销的外连接条件。
5. 被 const 表优化的处理程序阻止。
6. 将不会被使用,通常是因为它们是流式传输的而不是物化的(请参阅 Query_expression::can_materialize_directly_into_result())。
7. 位于完整连接的两侧
// 如果找到表有索引,这里用到的keyuse在之前JOIN::update_ref_and_keys()已经获取到。
if (eq_part.is_prefix(table->key_info[key].user_defined_key_parts)) {
// 该索引是唯一索引
if (table->key_info[key].flags & HA_NOSAME) {
if (const_ref == eq_part) {
// 标识该表是const table
mark_const_table(tab, start_keyuse);
// 改变table的状态为const
join_read_const_table(tab, positions + const_tables - 1);
}
}
}
}
} while ((const_table_map & found_ref) && ref_changed);
以下是实际使用的时候表扫描方式类型汇总,其中 JT_CONST 和 JT_SYSTEM 就是我们本章要说明的。JT_SYSTEM 类型,这个需要跟 JT_CONST 区分开,JT_SYSTEM 主要是扩展表而不是物理表,JT_SYSTEM 表没有索引。JT_SYSTEM 类型也会被计入 const_tables,详情见下面。
bk.wekochat.com/jasl/c4FSw.wAp
bk.huanbao580.com/deyz/f8W4d.wAP
bk.vwotech.com/meyl/c4FSw.wAp
bk.shplcchina.com/f8W4d.wAP
bk.cdkenxb120.com/c5W4R.WAp
bk.shplcchina.com/0wSwf.Wap
bk.51yjjy.com/asd7/0wSwf.Wap
bk.szlcdpq.com/dcwl/D30eq.wAP
bk.jinduoceramics.com/0wSwf.Wap
bk.xintiao78.com/jasl/D30eq.wAP
join_type 访问方法的类型 说明
JT_UNKNOWN 无效
JT_SYSTEM 表只有一行,比如 select * from (select 1)
JT_CONST 表最多只有一行满足,比如 WHERE table.pk = 3
JT_EQ_REF '= 符号用在唯一索引
JT_REF '= 符号用在非唯一索引
JT_ALL 全表扫描
JT_RANGE 范围扫描
JT_INDEX_SCAN 索引扫描
JT_FT Fulltext 索引扫描
JT_REF_OR_NULL 包含 null 值,比如 "WHERE col = ... OR col IS NULL
JT_INDEX_MERGE 一张表执行多次范围扫描最后合并结果
-- 下面的select 1表类型就是system而不是const。但是select 1这张表的数量也会计入const_tables
greatsql> EXPLAIN SELECT * FROM (SELECT 1);
+----+-------------+------------+------------+--------+---------------+------+---------+------+------+----------+----------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+--------+---------------+------+---------+------+------+----------+----------------+
| 1 | PRIMARY | | NULL | system | NULL | NULL | NULL | NULL | 1 | 100.00 | NULL |
| 2 | DERIVED | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
+----+-------------+------------+------------+--------+---------------+------+---------+------+------+----------+----------------+
2 rows in set, 1 warning (12.33 sec)
三、实际例子说明
接下来看几个例子来说明上面的代码。

greatsql> CREATE TABLE t2 (c1 int, c3 varchar(32));
greatsql> CREATE index idx1 ON t2(c1);
greatsql> INSERT INTO t2 VALUES (1,'aaa'),(2,'bbb');

-- 非唯一索引不是const table
greatsql> EXPLAIN SELECT * FROM t2 WHERE c1=1 AND c1<10;
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
| 1 | SIMPLE | t2 | NULL | ref | idx1 | idx1 | 4 | const | 1 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
1 row in set, 1 warning (3.84 sec)

-- 改变c1为primary key,看一下结果。
-- between条件也是唯一条件,因此是const table
-- 这里有个约束条件:BETWEEN的上下界条件值必须一样,才会被判定为const,否则是range
greatsql> EXPLAIN SELECT * FROM t1 WHERE c1 BETWEEN 1 AND 1 AND c1<10;
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| 1 | SIMPLE | t1 | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | NULL |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

-- value in后面的值即使最小值和最大值相同也走的范围扫描,不被判定为const table
greatsql> EXPLAIN SELECT * FROM t1 WHERE c1 IN (1,1) AND c1<10;
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| 1 | SIMPLE | t1 | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 1 | 100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.01 sec)

-- 下面的表只有一行,但是由于引擎不是MyISAM或者memory而不被判定为const table
greatsql> CREATE TABLE t3 AS SELECT 1 AS c1;
greatsql> EXPLAIN SELECT * FROM t3 WHERE c1=1;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | t3 | NULL | ALL | NULL | NULL | NULL | NULL | 1 | 100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (1.91 sec)

-- 下面的表只有一行,由于引擎是MEMORY而被判定为const table
greatsql> CREATE TABLE t5 engine=memory AS SELECT 1 AS c1;
greatsql> EXPLAIN SELECT * FROM t5 WHERE c1=1;
+----+-------------+-------+------------+--------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+--------+---------------+------+---------+------+------+----------+-------+
| 1 | SIMPLE | t5 | NULL | system | NULL | NULL | NULL | NULL | 1 | 100.00 | NULL |
+----+-------------+-------+------------+--------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (2.70 sec)

-- 两张表进行join的时候,即使这里t1的顺序在后面,因为在优化器里面被判定为const table,所以顺序被提前到第一位。
greatsql> EXPLAIN SELECT t1.c1,t1.c2 FROM t2,t1 WHERE t1.c1=1 AND t1.c1<10;
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | t1 | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | NULL |
| 1 | SIMPLE | t2 | NULL | index | NULL | idx1 | 4 | NULL | 1 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
2 rows in set, 1 warning (2.70 sec)

greatsql> EXPLAIN FORMAT=TREE SELECT t1.c1,t1.c2 FROM t2,t1 WHERE t1.c1=1 AND t1.c1<10;
+-----------------------------------------------------+
| EXPLAIN
bk.shuixitech.com/deyz/c4FSw.wAp
bk.bctiantuo.com/jasl/f8W4d.wAP
bk.51jyo.com/cliq/c4FSw.wAp
bk.jinduoceramics.com/0wSwf.Wap
bk.kfamaw.com/deyz/0wSwf.Wap
bk.huaxinlighting.com/cliq/fX8Xw.WaP
bk.shplcchina.com/deyz/c4FSw.wAp
bk.sdymsxfh.com/asd7/c5W4R.WAp
bk.zjbhzs.com/dcwl/c5W4R.WAp
bk.testoppo.com/meyl/c4FSw.wAp
+-----------------------------------------------------+
| -> Index scan on t2 using idx1 (cost=0.35 rows=1) |
+-----------------------------------------------------+
1 row in set (40.27 sec)

-- 通过打印堆栈查看当前最佳的排列顺序,可以看到表t1确实被提到第一个了。
Thread 56 "connection" hit Breakpoint 16, JOIN::get_best_combination (this=0x7fff14c6d0f0)
at /sql/sql_optimizer.cc:3663
3663 for (Table_ref *sj_nest : query_block->sj_nests) {
(gdb) p best_ref[0]->table_ref->table_name
$99 = 0x7fff14c5d660 "t1"
(gdb) p best_ref[1]->table_ref->table_name
$100 = 0x7fff14c5d538 "t2"
四、总结
从上面优化器最早的步骤我们认识了 const table 的定义和判定方法,可以发现实际运用中 const table 是可以提高查询速度的。这里面通过唯一索引来定位查找数据是最快的就是因为被判定为 const table,在后面的实践里面发现 =(等值查询)、特殊情况下的 BETWEEN 的时候都可以被认为是 const table,但是 IN 却不行,因此实际运用的时候尽量不要用 IN 条件,而多用等值条件 和 特殊条件下的BETWEEN 来查询,最好是只用等值条件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/829022.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一文读懂远程控制协议—Remote Control Protocol

RCP是一种轻量级的通信协议,核心理念是将边缘节点控制器中MCU的协议转换功能迁移至区域控制器ZCU甚至中央控制器Central ECU中实现,从而实现针对边缘节点的远程控制,实现网络中软件集中化,边缘节点轻量化。 随着中央计算+区域控制的中央集中式架构广泛应用,10BASE-T…

2024-2025-1 20241305 《计算机基础与程序设计》第七周学习总结

作业信息这个作业属于哪个课程 2024-2025-1-计算机基础与程序设计(https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP)这个作业要求在哪里 2024-2025-1计算机基础与程序设计第七周作业这个作业的目标 1、数组与链表2、基于数组和基于链表实现数据结构3、无序表与有序表4、…

OSSFileBrowse:OSS存储桶遍历漏洞利用工具

简介: 由于经常遇到存储桶遍历漏洞,直接访问文件是下载,不方便预览,且甲方要求证明该存储桶的危害,因此该工具应运而生。 使用javafx做图形化,kkFileView做文件预览接口。 使用: 命令行运行: java -Dfile.encoding=UTF-8 -jar OSSFileBrowse-1.0-SNAPSHOT.jar或者直接点…

NetExec:新型内网/域渗透工具

免责声明 仅供安全研究与学习之用,若将工具做其他用途,由使用者承担全部法律及连带责任,作者及发布者不承担任何法律及连带责任。简介: NetExec是一款强大的自动化网络安全评估和漏洞测试工具,作为已停止维护的CrackMapExec(CME)的现代替代品,它已被渗透测试人员和红队成…

2024-2025-1 20241407《计算机基础与程序设计》第七周学习总结

这个作业属于哪个课程 [2024-2025-1 计算机基础与程序设计](https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP)这个作业要求在哪里 2024-2025-1计算机基础与程序设计第七周作业这个作业的目标 学习数组与链表,基于数组和基于链表实现数据结构,无序表与有序表,树,图…

mysql ubuntu 卸载

mysql 卸载 :引用https://developer.aliyun.com/article/1306777 在 Ubuntu 系统中,MySQL 是一种常用的关系型数据库服务器。有时,我们可能需要完全卸载 MySQL 服务器,包括所有配置文件和数据,以便重新安装或切换到其他数据库服务器。本文将详细介绍在 Ubuntu 中如何完全卸…

MySQLMonitor: 黑盒测试Mysql实时监控辅助工具

MySQLMonitor MySQL实时监控工具(代码审计、黑盒测试辅助工具)使用 1.自行打包使用 git clone https://github.com/fupinglee/MySQLMonitorcd MySQLMonitormvn clean package -DskipTests=true打开target下的jar文件即可执行 2.直接下载使用 https://github.com/fupinglee/My…

初始mysql以及创建

mysql是一个客户端服务器结构的程序 mysql的服务器是真正的本体,负责保存和管理数据,数据都是保存在硬盘上 数据库服务器上可以把很多有业务上联系的表放在一起,构成一个逻辑上的数据集合登陆mysql 打开终端输入mysql -u root -p,然后显示这个就说明mysql客户端连接到了服务…

【论文阅读笔记】Transformer——《Attention Is All You Need》

论文地址:https://arxiv.org/pdf/1706.03762 代码地址:https://github.com/huggingface/transformers目录IntroductionBackgroundModel ArchitectureEncoderLN and BNDecoderAttentionMulti-head AttentionFeed-ForwardPostion Encoding IntroductionRNN,LSTM 处理时序信息的…

Trivy : 容器安全利器

在当今数字化时代,容器化技术已经成为软件开发和部署的重要组成部分。然而,随着容器数量的增加,安全问题也日益突出。为了确保容器环境的安全,我们需要一款强大的工具来检测容器中的漏洞。今天,我将为大家介绍一款优秀的容器漏洞扫描工具:Trivy Container Scanner。本文将…

Hive3.1.2搭建文档包含详细步骤及相关截图以及常见问题解决

hive-3.1.2分布式搭建文档 1、下载,上传,解压,配置环境变量# 1、解压(解压到上级目录) tar -zxvf apache-hive-3.1.2-bin.tar.gz -C..# 2、重名名 mv apache-hive-3.1.2-bin hive-3.1.2# 3、配置环境变量 vim /etc/profile# 4、在最后增加配置 export HIVE_HOME=/usr/loca…

dbeaver连接MySQL出现了 Public Key Retrieval is not allowed 错误

问题现象出现这个错误的原因 错误提示“Public Key Retrieval is not allowed”通常出现在尝试使用SSL(Secure Sockets Layer)连接到MySQL数据库时。这可能是由于以下原因之一导致的:MySQL服务器配置:MySQL服务器可能没有正确配置以允许公钥检索。 检查MySQL服务器的my.cnf…