在保持逻辑的同时加入子参数

时间:2012-03-21 18:45:15

标签: php mysql

我正在尝试优化慢速查询,并且我遇到了以下情况(一直运行超过8秒)。

SELECT entryID, entryID AS iE, 0 AS eE, 'clarus1' AS locationID, dateStamp, amount AS income, NULL AS expense, reconciled, leaseID AS vendorID, incomeID AS expenseID
FROM structu_income.iLedger 
WHERE (dateStamp BETWEEN '2009-04-16' AND '2012-02-29') AND incomeID IS NOT NULL
    AND (
        leaseID IN (
            SELECT lease.leaseID FROM structu_assets.lease WHERE lease.unitID IN (
                SELECT unit.unitID FROM structu_assets.unit WHERE unit.locationID = 'clarus1'
            )
        )
        OR locationID IN (SELECT locationID FROM structu_assets.deed WHERE ownerID = 'clarus')
    )

这是EXPLAIN

enter image description here

我的想法是重构子查询以使用JOIN。但保持逻辑OR会让我失望。

此外,嵌套的子查询似乎是不可避免的。除非我在单独的查询中预定了unitID

我不是原始开发者。但我负责在不修改现有代码库或架构的情况下使其更高性能。所以我正在尝试选择慢速查询。

顺便说一下,跨数据库查询是否会影响性能?

2 个答案:

答案 0 :(得分:1)

为dateStamp列添加索引。

使用:

dateStamp > '2009-04-16' AND dateStamp < '2012-02-29'

而不是:

dateStamp BETWEEN '2009-04-16' AND '2012-02-29'

效率更高。

最后,您可以在PHP中编写循环而不是子查询。

答案 1 :(得分:1)

看看这个答案 a)是否有效并且 b)更快会很有趣。试试这个:

SELECT
    il.entryID,
    il.entryID AS iE,
    0 AS eE,
    'clarus1' AS locationID,
    il.dateStamp,
    il.amount AS income,
    NULL AS expense,
    il.reconciled,
    il.leaseID AS vendorID,
    il.incomeID AS expenseID
FROM
    structu_income.iLedger il
    INNER JOIN structu_assets.lease l ON il.leaseID = l.leaseID
    INNER JOIN structu_assets.unit u ON l.unitID = u.unitID AND u.locationID = 'clarus1'
WHERE
    il.dateStamp BETWEEN '2009-04-16' AND '2012-02-29'
    AND il.incomeID IS NOT NULL
UNION
SELECT
    il.entryID,
    il.entryID AS iE,
    0 AS eE,
    'clarus1' AS locationID,
    il.dateStamp,
    il.amount AS income,
    NULL AS expense,
    il.reconciled,
    il.leaseID AS vendorID,
    il.incomeID AS expenseID
FROM
    structu_income.iLedger il
    INNER JOIN structu_assets.deed d ON il.locationID = d.locationID AND d.ownerID = 'clarus'
WHERE
    il.dateStamp BETWEEN '2009-04-16' AND '2012-02-29'
    AND il.incomeID IS NOT NULL

第一个SELECT查询会处理OR条件的前半部分,第二个SELECT查询会在后半部分的结果中添加UNION个查询。并且你不应该使用{{1}}获得重复的行,所以我相信你应该得到相同的结果。