然后解释一下能裁剪和不能裁剪的场景,以及为什么…
select * from quarterly_report_status where report_updated > UNIX_TIMESTAMP('2008-01-01 00:00:00');
这个不能裁剪,是因为 UNIX_TIMESTAMP(‘2008-01-01 00:00:00’) 的结果实际上是一个 int 类型,而 report_updated 是 timestamp 类型,在这两者比较的时候,cast 规则有一点问题,int 类型转 timestamp 类型后转成了 nil (bug)
你可以验证这一点:
mysql> explain select * from quarterly_report_status partition (p0) where report_updated > UNIX_TIMESTAMP('2008-01-01 00:00:00');
+---------------------+----------+------+------------------------------------------------------------------------------------------------+
| id | count | task | operator info |
+---------------------+----------+------+------------------------------------------------------------------------------------------------+
| TableReader_8 | 0.00 | root | data:Selection_7 |
| └─Selection_7 | 0.00 | cop | gt(test.quarterly_report_status.report_updated, NULL) |
| └─TableScan_6 | 10000.00 | cop | table:quarterly_report_status, partition:p0, range:[-inf,+inf], keep order:false, stats:pseudo |
+---------------------+----------+------+------------------------------------------------------------------------------------------------+
3 rows in set, 1 warning (0.00 sec)
实际上使用的 条件是 report_updated > nil 恒为 true 的,所以分区裁剪模块裁剪不掉
gt(test.quarterly_report_status.report_updated, NULL)
我记录了另外一个 issue https://github.com/pingcap/tidb/issues/12028
然后
select * from quarterly_report_status where report_updated > '2008-01-01 00:00:00';
这个裁剪不掉,是因为你条件没写对,它本来就落在 p0 p1 p2 p3 分区里面,你要改成小于是能裁剪的,比如
select * from quarterly_report_status where report_updated < '2007-01-01 00:00:00';
再然后
select * from quarterly_report_status where report_updated > '2008-05-01 00:00:00';
这个的裁剪做的不准确,裁剪后应该是 p2 p3,而当前的 TiDB 裁剪后是 p0 p2 p3
原因是要做大于,小于,这类场景 p0 不太好裁剪,因为 “当计算结果为 NULL 的时候默认在 p0 分区”,大于小于不好预测结果是否为 NULL (有待优化)
然后
select * from quarterly_report_status where unix_timestamp(report_updated) > '2019-05-01 00:00:00';
这个裁剪不掉,有好几个问题。一个是 unix_timestamp 没有下推,其实这是一个不必要的限制,当时跟同事争执了好久。反正就是 TiDB 目前有这个约束在:如果不能下推的函数,相关的表达式就不能执行分区裁剪。
另外一个就是如果分区条件是 f(x) op const,然后查询条件是 g(x) op const,op 是大于小于之类的,这种规则我们没有支持。也就是条件里面有两个函数存在的时候。这种理论上是没法实现的,只有特定的场景 f 跟 g 是同一个函数,规则不太通用。