为什么有些时候用prewhere是错误的。
Prewhere和where语句的作用相同,用来过滤数据。不同之处在于prewhere只支持*MergeTree族系列引擎的表,首先会读取指定的列数据,来判断数据过滤,等待数据过滤之后再读取select声明的列字段来补全其余属性。
当查询列明显多于筛选列时使用PreWhere可十倍提升查询性能,Prewhere会自动优化执行过滤阶段的数据读取方式,降低io操作。参数optimize_move_to_prewhere=1为开启状态,可以设置为0对其关闭。
在某些场合下,prewhere语句比where语句处理的数据量更少性能更高。
默认情况,我们肯定不会关闭where自动优化成prewhere,但是某些场景即使开启优化,也不会自动转换成prewhere,需要手动指定prewhere:
- 使用常量表达式
- 使用默认值为alias类型的字段
- 包含了arrayJOIN,globalIn,globalNotIn或者IndexHint的查询
- select查询的列字段和where的谓词相同
- 使用了主键字段
由于prewhere会在聚合阶段前去拿数据,对于一些易变的字段就不适合用prewhere。
那如果我的表数据只做存储是不是意味着没有什么可变字段
不完全是这样。即使表数据主要用于存储,也并不意味着没有可变字段,也不意味着可以随意使用 PREWHERE
。以下是几个关键点:
- 数据