严格日期的条件比提取日期间隔慢得多

时间:2017-03-29 19:31:38

标签: sql performance postgresql optimization

我有两个查询集,它收集了相同的结果,但我使用不同的方法来查看特定年份的特定月份。

在第一种情况下,我使用整个日期本身和'01'的日期,在第二种情况下,我使用BETWEEN来选择年份和EXTRACT这个月。

在我的第一个场景中,查询集需要超过2百万才能执行,而在第二种情况下,查询集几乎立即执行。

这里是相关查询:

第一个案例

SELECT [lot of fields]
FROM "dsn_consolidationcontrat" 
INNER JOIN "dsn_consolidationindividu" ON ("dsn_consolidationcontrat"."individu_id" = "dsn_consolidationindividu"."id") 
INNER JOIN "dsn_consolidationetablissement" ON ("dsn_consolidationcontrat"."etablissement_id" = "dsn_consolidationetablissement"."id") 
INNER JOIN "dsn_consolidationentreprise" ON ("dsn_consolidationetablissement"."entreprise_id" = "dsn_consolidationentreprise"."id") 
LEFT OUTER JOIN "dsn_consolidationcontrat" T5 ON ("dsn_consolidationcontrat"."contrat_precedent_id" = T5."id") 
LEFT OUTER JOIN "dsn_consolidationcontratfin" ON ("dsn_consolidationcontrat"."id" = "dsn_consolidationcontratfin"."contrat_id") 
WHERE ("dsn_consolidationcontrat"."id" IN (
    SELECT U0."consolide_id" FROM "dsn_historiquecontrat" U0 
    INNER JOIN "dsn_declaration" U1 ON (U0."declaration_courante_id" = U1."id") 
    WHERE U1."mois" = '2016-12-01'::date) 
AND NOT ("dsn_consolidationcontrat"."id" IN (
    SELECT U2."contrat_id" FROM "dsn_historiquecontratfin" U0 
    INNER JOIN "dsn_declaration" U1 ON (U0."declaration_courante_id" = U1."id") 
    INNER JOIN "dsn_consolidationcontratfin" U2 ON (U0."consolide_id" = U2."id") 
    WHERE U1."mois" = '2016-12-01'::date)) 
AND NOT ("dsn_consolidationcontrat"."id" IN (
    SELECT U0."consolide_id" FROM "dsn_historiquecontrat" U0 
    INNER JOIN "dsn_declaration" U1 ON (U0."declaration_courante_id" = U1."id") 
    WHERE (U1."mois" = '2017-01-01'::date AND U0."declaration_precedente_id" IS NOT NULL)))) 
LIMIT 10

第二个案例

SELECT [lot of fields]
FROM "dsn_consolidationcontrat" 
INNER JOIN "dsn_consolidationindividu" ON ("dsn_consolidationcontrat"."individu_id" = "dsn_consolidationindividu"."id") 
INNER JOIN "dsn_consolidationetablissement" ON ("dsn_consolidationcontrat"."etablissement_id" = "dsn_consolidationetablissement"."id") 
INNER JOIN "dsn_consolidationentreprise" ON ("dsn_consolidationetablissement"."entreprise_id" = "dsn_consolidationentreprise"."id") 
LEFT OUTER JOIN "dsn_consolidationcontrat" T5 ON ("dsn_consolidationcontrat"."contrat_precedent_id" = T5."id") 
LEFT OUTER JOIN "dsn_consolidationcontratfin" ON ("dsn_consolidationcontrat"."id" = "dsn_consolidationcontratfin"."contrat_id") 
WHERE ("dsn_consolidationcontrat"."id" IN (
    SELECT U0."consolide_id" FROM "dsn_historiquecontrat" U0 
    INNER JOIN "dsn_declaration" U1 ON (U0."declaration_courante_id" = U1."id") 
    WHERE U1."mois" BETWEEN '2016-01-01'::date AND '2016-12-31'::date AND EXTRACT('month' FROM U1."mois") = 12)) 
AND NOT ("dsn_consolidationcontrat"."id" IN (
    SELECT U2."contrat_id" FROM "dsn_historiquecontratfin" U0 
    INNER JOIN "dsn_declaration" U1 ON (U0."declaration_courante_id" = U1."id") 
    INNER JOIN "dsn_consolidationcontratfin" U2 ON (U0."consolide_id" = U2."id") 
    WHERE (U1."mois" BETWEEN '2016-01-01'::date AND '2016-12-31'::date AND EXTRACT('month' FROM U1."mois") = 12))) 
AND NOT ("dsn_consolidationcontrat"."id" IN (
    SELECT U0."consolide_id" FROM "dsn_historiquecontrat" U0 
    INNER JOIN "dsn_declaration" U1 ON (U0."declaration_courante_id" = U1."id") 
    WHERE (U1."mois" BETWEEN '2017-01-01'::date AND '2017-12-31'::date AND U0."declaration_precedente_id" IS NOT NULL AND EXTRACT('month' FROM U1."mois") = 1)))) 
LIMIT 10

两个查询集的执行计划彼此非常不同:在第一种情况下,我们得到了一堆散列连接,后跟独特的操作,但在第二种情况下,我们有一个漂亮的嵌套循环序列。

感谢您的任何解释。

0 个答案:

没有答案