使用解释分析结果优化查询

时间:2015-04-17 09:08:19

标签: postgresql postgresql-performance

以下是我工会的一部分

SELECT tbl_12.AcGrCode
        ,tbl_12.AcId
        ,tbl_12.AcName
        ,tbl_11.AcgrName
        ,tbl_16.VrDate
        ,tbl_16.PDC
        ,tbl_16.VrDate::timestamp AS vdate
        ,tbl_16.VrNo
        ,to_char(tbl_16.vrdate, 'MM')::INT AS dateMonth
        ,to_char(tbl_16.vrdate, 'yyyy')::INT AS dateYear
        ,tbl_16.Refno
        ,tbl_02.VrName
        ,tbl_17.Narr
        ,CASE 
            WHEN tbl_16.VrId = 6
                THEN 0::DECIMAL
            ELSE tbl_17.Dr::DECIMAL
            END AS Dr
        ,CASE 
            WHEN tbl_16.VrId = 6
                THEN 0::DECIMAL
            ELSE tbl_17.Cr::DECIMAL
            END AS Cr
        ,tbl_16.AcyrId
        ,tbl_16.VrId
        ,(
            SELECT coalesce(SUM(tbl_17.Dr), 0::MONEY)
            FROM tbl_16
            INNER JOIN tbl_17 ON tbl_16.JrMId = tbl_17.JrmId
            WHERE tbl_16.BranchID = 1
                AND (tbl_17.AcId = tbl_12.AcId)
                AND (tbl_16.VrId = 6)
                AND (tbl_16.AcYrId = 6)
            ) AS OpDr
        ,(
            SELECT coalesce(SUM(tbl_17.Cr), 0::MONEY)
            FROM tbl_16
            INNER JOIN tbl_17 ON tbl_16.JrMId = tbl_17.JrmId
            WHERE tbl_16.BranchID = 1
                AND (tbl_17.AcId = tbl_12.AcId)
                AND (tbl_16.VrId = 6)
                AND (tbl_16.AcYrId = 6)
            ) AS OpCr
        ,(
            SELECT coalesce(SUM(tbl_17.Dr), 0::MONEY)
            FROM tbl_16
            INNER JOIN tbl_17 ON tbl_16.JrMId = tbl_17.JrmId
            WHERE tbl_16.BranchID = 1
                AND (tbl_17.AcId = tbl_12.AcId)
                AND (tbl_16.VrId <> 6)
                AND (tbl_16.AcYrId = 6)
                AND (
                    tbl_16.vrdate > Cast('2014-03-31' AS TIMESTAMP)
                    AND tbl_16.vrdate < Cast('2014-04-01' AS TIMESTAMP)
                    )
            ) AS OpperDr
        ,(
            SELECT coalesce(SUM(tbl_17.Cr), 0::MONEY)
            FROM tbl_16
            INNER JOIN tbl_17 ON tbl_16.JrMId = tbl_17.JrmId
            WHERE tbl_16.BranchID = 1
                AND (tbl_17.AcId = tbl_12.AcId)
                AND (tbl_16.VrId <> 6)
                AND (tbl_16.AcYrId = 6)
                AND (
                    tbl_16.vrdate > Cast('2014-03-31' AS TIMESTAMP)
                    AND tbl_16.vrdate < Cast('2014-04-01' AS TIMESTAMP)
                    )
            ) AS OpperCr
        ,tbl_47.AreaName
        ,tbl_16.JrmId
    FROM tbl_16
    INNER JOIN tbl_02 ON tbl_16.VrId = tbl_02.VrId
    INNER JOIN tbl_17 ON tbl_16.JrMId = tbl_17.JrmId
    INNER JOIN tbl_12 ON tbl_17.AcId = tbl_12.AcId
    INNER JOIN tbl_11 ON tbl_12.AcGrCode = tbl_11.AcgrCode
    INNER JOIN tbl_01 ON tbl_16.AcyrId = tbl_01.AcYrId
    LEFT OUTER JOIN tbl_22 ON tbl_16.RepId = tbl_22.RepId
    LEFT OUTER JOIN tbl_47 ON tbl_12.AreaId = tbl_47.AreaId
    WHERE tbl_16.BranchID = 1
        AND vrdate BETWEEN Cast('2014-04-01' AS TIMESTAMP)
            AND Cast('2014-04-30' AS TIMESTAMP)
        AND (tbl_16.AcYrId = 6)
        AND tbl_16.VrId <> 6
        AND tbl_12.acid <> 1

这个选择执行得非常慢,我只是对这个选择进行解释分析,我得到以下stats.I不知道如何使用它来提高查询性能

explain-analyze

1 个答案:

答案 0 :(得分:1)

一个人不需要执行计划就能看到你一次又一次地选择相同的数据。当然这很慢。将子查询移动到一个派生表表达式并改为使用它。

SELECT tbl_12.AcGrCode
        ,tbl_12.AcId
        ,tbl_12.AcName
        ,tbl_11.AcgrName
        ,tbl_16.VrDate
        ,tbl_16.PDC
        ,tbl_16.VrDate::timestamp AS vdate
        ,tbl_16.VrNo
        ,to_char(tbl_16.vrdate, 'MM')::INT AS dateMonth
        ,to_char(tbl_16.vrdate, 'yyyy')::INT AS dateYear
        ,tbl_16.Refno
        ,tbl_02.VrName
        ,tbl_17.Narr
        ,CASE WHEN tbl_16.VrId = 6 THEN 0::DECIMAL ELSE tbl_17.Dr::DECIMAL END AS Dr
        ,CASE WHEN tbl_16.VrId = 6 THEN 0::DECIMAL ELSE tbl_17.Cr::DECIMAL END AS Cr
        ,tbl_16.AcyrId
        ,tbl_16.VrId
        ,coalesce(agg.OpDr, 0::MONEY) AS OpDr
        ,coalesce(agg.OpCr, 0::MONEY) AS OpCr
        ,coalesce(agg.OpperDr, 0::MONEY) AS OpperDr
        ,coalesce(agg.OpperCr, 0::MONEY) AS OpperCr
        ,tbl_47.AreaName
        ,tbl_16.JrmId
    FROM tbl_16
    INNER JOIN tbl_02 ON tbl_16.VrId = tbl_02.VrId
    INNER JOIN tbl_17 ON tbl_16.JrMId = tbl_17.JrmId
    INNER JOIN tbl_12 ON tbl_17.AcId = tbl_12.AcId
    INNER JOIN tbl_11 ON tbl_12.AcGrCode = tbl_11.AcgrCode
    INNER JOIN tbl_01 ON tbl_16.AcyrId = tbl_01.AcYrId
    LEFT OUTER JOIN tbl_22 ON tbl_16.RepId = tbl_22.RepId
    LEFT OUTER JOIN tbl_47 ON tbl_12.AreaId = tbl_47.AreaId
    LEFT OUTER JOIN
    (
      SELECT 
        t17.AcId, 
        SUM(t17.Dr) AS OpDr,
        SUM(t17.Cr) AS OpCr,
        SUM(CASE WHEN t16.vrdate > Cast('2014-03-31' AS TIMESTAMP) AND t16.vrdate < Cast('2014-04-01' AS TIMESTAMP) THEN t17.Dr END) AS OpperDr,
        SUM(CASE WHEN t16.vrdate > Cast('2014-03-31' AS TIMESTAMP) AND t16.vrdate < Cast('2014-04-01' AS TIMESTAMP) THEN t17.Cr END) AS OpperCr
      FROM tbl_16 t16
      INNER JOIN tbl_17 t17 ON t16.JrMId = t17.JrmId
      WHERE t16.BranchID = 1 AND t16.VrId <> 6 AND t16.AcYrId = 6
      GROUP BY t17.AcId
    ) AS agg ON agg.AcId = tbl_12.AcId
    WHERE tbl_16.BranchID = 1
      AND vrdate BETWEEN Cast('2014-04-01' AS TIMESTAMP) AND Cast('2014-04-30' AS TIMESTAMP)
      AND tbl_16.AcYrId = 6
      AND tbl_16.VrId <> 6
      AND tbl_12.acid <> 1