PostgreSQL代码优化

时间:2012-10-26 10:51:12

标签: sql database performance postgresql

我有这段代码:

SELECT 
    rv_storage.m_product_id AS n_product_id,
    rv_storage.value,
    rv_storage.name,
    m_warehouse.name AS warehouse_name,
    rv_storage.qtyonhand,
    rv_transaction.m_transaction_id,

    CASE WHEN rv_transaction.movementtype = 'V+' THEN movementdate
    ELSE NULL END AS last_in,

    CASE WHEN rv_transaction.movementtype = 'C-' THEN movementdate
    ELSE NULL END AS last_out,

    rv_transaction.movementagedays,

    CASE WHEN (movementagedays < -90) AND (movementagedays >= -180)  THEN qtyonhand
    ELSE NULL END AS more_than_90,

    CASE WHEN movementagedays < -180 THEN qtyonhand
    ELSE NULL END AS more_than_180
FROM
    adempiere.rv_storage
    INNER JOIN
    adempiere.rv_transaction ON
        rv_transaction.m_product_id = rv_storage.m_product_id 
        AND rv_transaction.movementagedays = (
            SELECT MAX(movementagedays) 
            FROM adempiere.rv_transaction 
            WHERE
                rv_transaction.m_product_id = rv_storage.m_product_id 
                AND rv_transaction.movementtype = 'C-'
                OR rv_transaction.movementtype = 'V+'
            )
    INNER JOIN
    adempiere.m_warehouse ON
        m_warehouse.m_warehouse_id = rv_storage.m_warehouse_id
WHERE rv_storage.m_product_id IN (
    SELECT m_product_id
    FROM adempiere.rv_transaction
    WHERE movementagedays < -90
    )
ORDER BY n_product_id;

结果如下表所示:

table http://img9.imageshack.us/img9/4506/table3n.png

但是在具有实时数据的服务器上(每个表上有100k +行),它太慢了。 有人可以告诉我如何优化代码?

谢谢

2 个答案:

答案 0 :(得分:1)

where子句中的子查询是多余的。我认为你在内连接的子查询的where子句中缺少一个括号:

SELECT 
    rv_storage.m_product_id AS n_product_id,
    rv_storage.value,
    rv_storage.name,
    m_warehouse.name AS warehouse_name,
    rv_storage.qtyonhand,
    rv_transaction.m_transaction_id,

    CASE WHEN rv_transaction.movementtype = 'V+' THEN movementdate
    ELSE NULL END AS last_in,

    CASE WHEN rv_transaction.movementtype = 'C-' THEN movementdate
    ELSE NULL END AS last_out,

    rv_transaction.movementagedays,

    CASE WHEN (movementagedays < -90) AND (movementagedays >= -180)  THEN qtyonhand
    ELSE NULL END AS more_than_90,

    CASE WHEN movementagedays < -180 THEN qtyonhand
    ELSE NULL END AS more_than_180
FROM
    adempiere.rv_storage
    INNER JOIN
    adempiere.rv_transaction ON
        rv_transaction.m_product_id = rv_storage.m_product_id 
        AND rv_transaction.movementagedays = (
            SELECT MAX(movementagedays) 
            FROM adempiere.rv_transaction 
            WHERE
                rv_transaction.m_product_id = rv_storage.m_product_id 
                AND (rv_transaction.movementtype = 'C-'
                    OR rv_transaction.movementtype = 'V+')
            )
    INNER JOIN
    adempiere.m_warehouse ON
        m_warehouse.m_warehouse_id = rv_storage.m_warehouse_id
WHERE movementagedays < -90
ORDER BY n_product_id;

现在发布解释输出。

答案 1 :(得分:0)

IN()和NOT IN()子查询的优化程度很低: MySQL将子查询作为外部查询中每一行的从属子查询执行。这是MySQL 5.5及更早版本中严重性能问题的常见原因。该查询可能应分别重写为JOIN或LEFT OUTER JOIN。