优化使用日期进行过滤和连接的 SQL 查询

Posted

技术标签:

【中文标题】优化使用日期进行过滤和连接的 SQL 查询【英文标题】:Optimizing SQL Query which uses dates for filtering and joins 【发布时间】:2017-10-26 06:35:00 【问题描述】:

我有一个需要优化的 SQL 查询,因为它现在似乎永远运行。 我已经运行了 5 个多小时,但它似乎并没有结束。

SELECT 
a.HD_ID,
CASE WHEN date_from > b.date_tag THEN date_from
        ELSE b.date_tag
END date_from1,
CASE WHEN trunc(date_to)=b.date_tag THEN date_to
        ELSE b.date_tag + interval '23 hours, 59 minutes,59 seconds'
END date_to1
FROM table1 a
JOIN table2 b
ON (b.date_tag between trunc(date_from) and date_to) 
WHERE a.first_date between '2015-08-11' and sysdate-3;

我认为问题出在日期字段上,但我不知道有什么方法可以优化日期操作。 有人可以帮我解决这个问题吗?

【问题讨论】:

尝试将索引添加到date_tagdate_fromdate_to,以及first_date。您也可以在前后运行EXPLAIN,看看是否有帮助。 添加您正在使用的 DBMS 的标签 PostgreSQL 中没有sysdate。请将EXPLAIN (ANALYZE, BUFFERS) SELECT ... 的输出添加到问题中。 除了对解释计划等的请求 - 从 Table1 到 Table2 的连接似乎只引用 table2 和 date_from / date_to - 但没有给出这些值的来源(没有表别名,它们也是输入参数?)如果两个字段都不是来自table1,则会导致笛卡尔效应。笛卡尔是必需的,还是 table1 中的那些字段之一? 您确定此代码没有很多重复项吗?您只是按日期加入他们,这是很少做的事情。 【参考方案1】:

请尝试:

SELECT 
a.HD_ID,
CASE WHEN date_from > b.date_tag THEN date_from
ELSE b.date_tag
END date_from1,
CASE WHEN trunc(date_to)=b.date_tag THEN date_to
ELSE b.date_tag + interval '23 hours, 59 minutes,59 seconds'
END date_to1
FROM table1 a
JOIN table2 b
ON trunc(date_from) >= b.date_tag <= date_to
WHERE '2015-08-11' >= a.first_date <= sysdate-3;

【讨论】:

以上是关于优化使用日期进行过滤和连接的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

记录一个sql优化后大大提高查询效率的情形

mysql sql优化和sql执行计划

优化连接查询,需要“过滤”不同的

SQL Big Query 完全连接表以使用相同的过滤器

SQL执行与优化

使用多个连接和条件优化 SQL 查询