【GreatSQL优化器-03】查询开销估算

【GreatSQL优化器-03】查询开销估算

一、cost和read_time介绍

GreatSQL的优化器在创建执行计划的时候是根据每张表的行数和数据分布以及读数据硬盘消耗等信息来判断先查询哪张表后查询哪张表,要不要使用索引,这些表资源信息就被称为cost,俗称为"开销"。在这之前已经执行了update_ref_and_keys(参考【GreatSQL优化器-02】)和extract_const_tables(参考【GreatSQL优化器-01】),拿到了const tables信息和表的keyuse_array索引信息,这里就开始计算单张表扫描的开销,做一个初步的估计,用来给后面的choose_table_order()搜索最佳表顺序提供原始数据信息。

优化器通过estimate_rowcount函数初步计算单表开销,这个函数最后会计算出3个重要的数据。

名称 说明 计算公式
found_records 表的总行数 tab->table()->file->stats.records
read_time 读取所有数据需要的开销 io_cost + cpu_cost + import_cost
worst_seeks 扫描全表需要的最差开销 find_worst_seeks(tab->table(), tab->found_records, tab->read_time)根据上面2项计算得出

下面用一个简单的例子来说明这三个数字怎么查看:

greatsql> CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT,date1 DATETIME);
greatsql> INSERT INTO t1 VALUES (1,10,'2021-03-25 16:44:00.123456'),(2,1,'2022-03-26 16:44:00.123456'),(3,4,'2023-03-27 16:44:00.123456'),(5,5,'2024-03-25 16:44:00.123456');
greatsql> CREATE TABLE t2 (cc1 INT PRIMARY KEY, cc2 INT);
greatsql> INSERT INTO t2 VALUES (1,3),(2,1),(3,2),(4,3),(5,15);
greatsql> CREATE INDEX idx1 ON t1(c2);
greatsql> CREATE INDEX idx2 ON t1(c2,date1);
greatsql> CREATE INDEX idx2_1 ON t2(cc2);
greatsql> SET optimizer_trace = 'enabled=ON' ;

greatsql> SELECT * FROM t2,t1,(select 10) t3 where t1.c1=t2.cc2;
+-----+------+----+------+---------------------+----+
| cc1 | cc2  | c1 | c2   | date1               | 10 |
+-----+------+----+------+---------------------+----+
|   3 |    2 |  2 |    1 | 2022-03-26 16:44:00 | 10 |
|   1 |    3 |  3 |    4 | 2023-03-27 16:44:00 | 10 |
|   4 |    3 |  3 |    4 | 2023-03-27 16:44:00 | 10 |
|   2 |    1 |  1 |   10 | 2021-03-25 16:44:00 | 10 |
+-----+------+----+------+---------------------+----+
> SELECT * FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
          {
            "rows_estimation": [
              {
                "table": "`t2`",  -- 按照上面查询顺序t2放第一个
                "table_scan": {
                  "rows": 5, 因为t2非const表,因此这里显示的是所有行
                  "cost": 0.25, 这个是t2查询5条的开销,
                  "worst_seeks": 2 这里是另外加上去的,为了查看方便
                }
              },
              {
                "table": "`t1`", 按照上面查询顺序t1放第二个
                "table_scan": {
                  "rows": 4, 因为t1非const表,因此这里显示的是所有行
                  "cost": 0.25,
                  "worst_seeks": 2 这里是另外加上去的,为了查看方便
                }
              },
              {
                "table": " `t3`", 按照上面查询顺序t3放第三个
                "rows": 1,
                "cost": 1, ※这里有疑问,实际的read_time=worst_seeks=0.25,但是代码用了固定值1
                "worst_seeks": 0.25 这里是另外加上去的,为了查看方便
                "table_type": "system", 因为t3是const表,因此这里显示的system
                "empty": false
              }
            ]
          },

附表:代价系数

代价系数 说明
ROW_EVALUATE_COST 0.1 扫描一行需要的开销
KEY_COMPARE_COST 0.05 比较row id需要的开销
MEMORY_TEMPTABLE_CREATE_COST 1.0 创建临时表的开销,等于读10行
MEMORY_TEMPTABLE_ROW_COST 0.1 读或写一行到临时表
DISK_TEMPTABLE
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值