我有一个大约7M行(并且正在计数)的大表。我正在尝试优化SELECT以尽可能快。 SELECT来自单个表,没有连接。数据库是IBM Informix。 SELECT速度是优先级,但表中插入的数量非常恒定。
WHERE中有23个参数,但我已将日期和语言确定为值得索引的参数:
...
WHERE (? >= valid_from OR valid_from IS NULL)
AND (? <= valid_to OR valid_to IS NULL)
AND ((? >= date_from AND ? <= date_to) OR (? >= date_from AND ? <= date_to))
AND language = ?
...
现在,在那上创建索引的最佳方法是什么?
我是否从valid_from,valid_to,date_from,date_to和language创建单独的索引?或者我创建三个复合索引(valid_from,valid_to),(date_from,date_to)和语言?或者我用五个创建一个大的复合索引?所有字段都是必填字段。
被比较日期的索引是一个好主意,还是我应该仅限于那些使用=(完全匹配)的字段?
如果复合索引是这样的话,我想复合索引中字段的顺序很重要 - 如何在索引中对列进行排序?列date_from和date_to会给我最大的第一次减少,但是语言可能会让我更快地减少(虽然这是假设我凭空消失 - 见问题2)。
如果有多个索引,Informix是使用所有索引还是只使用一个(以及哪一个)?
我的测试显示WHERE中的条件顺序并不重要,但我可能错了 - 是吗?
WHERE中的某些条件是作为集合的列。 Informix不允许我索引这些列。这是否意味着这些条件与顺序扫描相匹配?将它们移到单独的表并加入它们是否合理有效?
到目前为止我做了什么:
答案 0 :(得分:1)
我也不知道Informix;你将不得不测试。 Postgres非常聪明,可以根据需要以明显的方式单独对变量进行单独的索引扫描,并且估计(并不总是那么好)这种方法是否优于表扫描。但是,我怀疑复合5列索引在这里运行良好。
我有另一个建议:使用默认值将日期的NULL值设置为无限极值;那么你没有特殊情况下的NULL。此外,这可能正确捕获业务逻辑。
如果两个?代表相同的参数,您可以使用(? >= date_from AND ? <= date_to)
略微简化? IS BETWEEN date_from and date_to
。只是语法糖,不会影响查询计划。
答案 1 :(得分:1)
您的和/或逻辑可能会使任何优化器对尝试创建有用的索引感到非常不满。
但是,您可以在Informix中创建功能索引,请参阅http://www.ibm.com/developerworks/data/library/techarticle/dm-0712wilcox/index.html。因此,对于这种方法,您可以创建用户定义的函数,以便您可以编写:
...
WHERE ? >= null_small_date(valid_from)
AND ? <= null_large_date(valid_to)
AND language = ?
// hack, hack. These 4 values should be the same as, but in a different order from
// the next line . This sanity check will let the index skip many possible records.
AND max_date(?, ?) >= date_from AND min_date(?, ?) <= date_to
AND ((? >= date_from AND ? <= date_to) OR (? >= date_from AND ? <= date_to))
...
考虑到这一点,您可以在(null_small_date(valid_from), null_large_date(valid_to), language, date_from, date_to)
上创建单个连锁索引,这样您就可以跳过大部分结果,只关注表格的一小部分。
答案 2 :(得分:1)
我还有一个人不知道Informix,所以这在黑暗中有点像。根据各列的选择性,您可能只能索引其中的一个或两个以实现所需的性能。
更新统计数据值得验证。它看起来也像Informix支持查询提示:
http://www.ibm.com/developerworks/data/zones/informix/library/techarticle/0502fan/0502fan.html
允许您准确指定要使用的索引。