在 StoneDB 中,如果在字段上使用函数,可能会导致SQL的性能下降,这是因为 StoneDB 的优化器无法对这类SQL做优化。
###创建表
CREATE TABLE jrk_all
(
`djxh` varchar(20) not null,
`dw` varchar(7) not null,
`zgswskfj_dm` varchar(11),
`rkrq` Date not null,
`skssqq` Date,
`skssqz` Date,
`yskm_dm` varchar(9),
`skgk_dm` varchar(10),
`jdxz_dm` varchar(9),
`zsxm_dm` varchar(5) not null,
`zspm_dm` varchar(9),
`hy_dm` varchar(4) not null,
`djzclx_dm` varchar(3),
`sksx_dm` varchar(4),
`skzl_dm` varchar(2),
`rklb` varchar(1),
`xtlb` varchar(1),
`se` Decimal(18, 2),
`zyj` Decimal(18, 2),
`ssj` Decimal(18, 2),
`dsj` Decimal(18, 2),
`qxj` Decimal(18, 2),
`xzj` Decimal(18, 2),
`zydfp` Decimal(18, 2),
`sjdfp` Decimal(18, 2)
) ENGINE=tianmu DEFAULT CHARSET=utf8;
###加载数据
load data infile '/tmp/2020_head.csv' into table jrk_all
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n';
mysql> select count(*) from jrk_all;
+----------+
| count(*) |
+----------+
| 11272192 |
+----------+
1 row in set (0.00 sec)
以上是表结构和表数据,执行如下SQL。
mysql> select sum(se) from jrk_all where year(rkrq)=2020;
+-----------------+
| sum(se) |
+-----------------+
| 545835530839.04 |
+-----------------+
1 row in set (3.74 sec)
Unoptimized expression near 'year' --->无法优化函数 year
Packs/packrows after KN evaluation: --->知识网格预估
(t0) Pckrows: 172, susp. 172 (0 empty 0 full). Conditions: 1 --->共计172个数据包,需要扫描172个数据包。
开启参数 tianmu_control_trace,从 trace.log 分析可知,如果字段出现函数,StoneDB 的优化器无法对这类SQL做优化。如果字段出现函数,需要读取所有数据包。这个问题就好比在 InnoDB中,索引字段使用了函数,导致了索引失效的问题,原本可以走索引扫描的执行计划,现在变成了全表扫描的执行计划。
对以上SQL做如下改写。
mysql> select sum(se) from jrk_all where rkrq between '2020-01-01' and '2020-12-31';
+-----------------+
| sum(se) |
+-----------------+
| 545835530839.04 |
+-----------------+
1 row in set (0.01 sec)
SQL的逻辑是查询字段 rkrq 等于2020年的总和,可以看到以上两个SQL业务逻辑是相同的,但两个SQL的性能还是有很大差异的,开启参数 tianmu_control_trace,看看 trace.log 是否有什么变化。
从 trace.log 分析可知,如果字段没有出现函数,直接从数据包节点读取元数据。