我有一个大型数据表,其中包含按日期和3个独立条件的详细信息,每个条件大约有12个离散值。也就是说,表中的每个条件字段都定义为12个值的ENUM。用户按日期和这三个条件的任何筛选提取汇总数据,包括根本不提取汇总数据。要使单个条件查找高效,需要3个单独的索引(date,CriteriaA)、(date,CriteriaB)、(date,CriteriaC)。如果您要根据3个(date,A,B,C)、(date,A,C)、(date,B,C)、(date,C)中的任何一个进行查找,则可以使用4个索引。
为了提高查找效率,我构建了一个SET列,其中包含来自3个条件的所有36个值。所有条件中的值都是唯一的,并且没有一个值是其他值的子集。我向该集合添加了一个索引(date,set_col)。但是,使用集合查找对此表进行的查询无法利用索引。FIND_IN_SET('Value',set_col)
、set_col LIKE '%Value%'
norset_col & [pos. in set]
触发索引(根据解释和整体结果集返回速度)。
是否有索引SET列的技巧?
我尝试了如下查询
Select Date, count(*)
FROM tbl
where DATE between [Start] and [End]
and FIND_IN_SET('Value',set_col)
group by Date
我希望它的运行速度与对单个条件列(具有索引)进行查找的速度一样快。但相反,当只存在对DATE的索引时,它的运行速度一样快。根据Explain处理的行数相同。
2条答案
按热度按时间ddrv8njm1#
不可能为任意查询索引SET列。
SET类型基本上是一个位字段,为您的集合定义的每个值都设置了一个位。您可以在这样的位字段中搜索 * 特定 * 位模式,也可以搜索特定位模式的范围或不等式等。但是,搜索在位字段中设置了一个特定位的行将是不可索引的。
FIND_IN_SET()实际上是在位域中搜索一个特定的位集。它不会为这个 predicate 使用索引。最好的优化方法是使用一个索引,根据
date
上的另一个搜索项缩小所检查的行。然后在与date
范围匹配的行中,将逐行应用FIND_IN_SET()。这与搜索子字符串的问题是一样的。下面的 predicate 不会在列上使用索引:
传统的数据索引是从字符串的 start 开始按字母顺序排列的,而不是从字符串中间的某个任意点开始。这就是为什么全文索引被创建为对整个字符串值的简单B树索引的替代方案。但是没有针对位字段的特殊索引类型。
我不认为SET数据类型对您的情况有帮助。您应该使用列排列的多列索引。
1rhkuytd2#
返回3个ENUM。然后
这些应该对查询有很大帮助,例如
也对
如果您还将有没有A/B/C的查询,则添加
注意:当使用“范围”时,
INDEX(date, A)
并不比INDEX(date)
更好,也就是说,我建议 * 反对 * 你提到的索引。FIND_IN_SET()
与几乎所有其它函数调用一样,不是sargable.但是,enum=const
是可优化搜索得,因为它是作为简单整数实现得.你没提到
这实际上是不可索引的。然而,我的建议总比没有好。