【发布时间】:2017-03-16 02:57:03
【问题描述】:
我们的数据库中有很多表,其中的数据仅在特定时间段内相关/有效。例如合同,它们有一个 start_date 和一个 end_date。而且不一定是整月。
现在这是针对此表的典型查询类型:
SELECT
*
FROM
contracts c
WHERE
c.start_date <= :1
AND c.end_date >= :2
AND c.region_id = :3
由于我们的表中有 20 年的数据(约 7000 天),因此日期是非常好的过滤标准,尤其是当 :1 和 :2 是同一天时。 region_id 不是一个很好的过滤条件,因为没有那么多(~50)。在此示例中,我们的表上有(除其他外)2 个索引:
contracts_valid_index (start_date, end_date)
contracts_region (region_id)
不幸的是,上述查询通常会使用contracts_region 索引,因为优化器认为它更便宜。这背后的原因很简单:当我在数据中间选择一天时,数据库会认为超过 start_date 的索引实际上并不好,因为它只会过滤掉一半的数据。通过查看 end_date ,同样适用。所以优化器认为他只能过滤掉我数据的1/4。因为他不知道 start_date 和 end_date 通常非常接近,而且这个索引会非常有选择性。
使用contracts_valid_index 的执行计划的成本高于使用contracts_region 的执行计划。但实际上contracts_valid_index要好得多。
我目前认为我不能通过制作更好的索引来加快查询速度(除了删除contracts_valid_index 之外的所有索引)。但也许我的数据模型对于查询优化器来说不是很好。所以我假设其他人也有类似的需求,并且很想知道他们如何建模数据或优化数据表/索引。
有什么建议吗?
【问题讨论】:
标签: oracle indexing query-optimization oracle12c