左联接比内部联接运行得快得多

时间:2019-04-20 19:53:33

标签: mysql sql

我一直在尝试优化我设法完成的查询的性能。使用左联接从36.7秒缩短到3.3秒,但是我不太明白为什么左联接与常规联接相比在性能上有如此大的提高。

两个查询回购的结果集是相同的。

以下是带有EXPLAIN的查询...

普通加入:36.7秒

SELECT t1.entityId, SUM(t2.gbp) AS amount
FROM transactionsV2 t1
JOIN
(
    SELECT
    t.uniqueId,
    ROUND((CASE WHEN t.currency != "GBP" THEN t.amount/er.exchange_rate ELSE t.amount END), 2) AS gbp
    FROM transactionsV2 t
    JOIN total_control.exchange_rates er 
    ON t.currency = er.currency
    ) t2
ON t1.uniqueId = t2.uniqueId
WHERE t1.paymentType IN ("DB", "3D")
AND t1.processing_time >= '2019-04-01 00:00:00'
AND t1.processing_time <= '2019-04-20 23:59:59'
AND t1.status = 1
GROUP BY t1.entityId

enter image description here

左加入:3.3秒

SELECT t1.entityId, SUM(t2.gbp) AS amount
FROM transactionsV2 t1
LEFT JOIN
(
    SELECT
    t.uniqueId,
    ROUND((CASE WHEN t.currency != "GBP" THEN t.amount/er.exchange_rate ELSE t.amount END), 2) AS gbp
    FROM transactionsV2 t
    JOIN total_control.exchange_rates er 
    ON t.currency = er.currency
    ) t2
ON t1.uniqueId = t2.uniqueId
WHERE t1.paymentType IN ("DB", "3D")
AND t1.processing_time >= '2019-04-01 00:00:00'
AND t1.processing_time <= '2019-04-20 23:59:59'
AND t1.status = 1
GROUP BY t1.entityId

enter image description here

3 个答案:

答案 0 :(得分:0)

您可以将其表示为相关子查询吗?

np.apply_along_axis

如果是这样,则可以将索引添加到基础表中以提高性能。但是,我怀疑交易表确实是一个视图。

答案 1 :(得分:0)

尽管我无法解释为什么它正在做它的工作...我不知道为什么当所有事务都源自TransactionsV2表时,您为何会自我联接。内部左联接正在拉动所有已加入汇率的交易,但没有应用任何位置,因此拉动了所有交易。然后在特定日期加入外部实例。

据我所见,您的TransactionV2表的结构类似于...

UniqueID auto-increment
EntityID (such as multiple transactions for this one person/company/entity)
Amount (based on relation to exchange rate and transaction amount)

因此,您将外部的每个唯一ID替换为内部的唯一ID 一旦汇率计算完成,但最终仍按实体分组... 我会尝试类似的东西。

SELECT
        t1.EntityID,
        SUM( ROUND(CASE WHEN t1.currency != "GBP" 
                        THEN t.amount/er.exchange_rate 
                        ELSE t.amount END, 2) ) Amount
    from
        TransactionsV2 t1
            LEFT JOIN total_control.exchange_rates er 
                ON t1.currency = er.currency
    WHERE 
            t1.paymentType IN ("DB", "3D")
        AND t1.processing_time >= '2019-04-01 00:00:00'
        AND t1.processing_time <= '2019-04-20 23:59:59'
        AND t1.status = 1
    GROUP BY 
        t1.entityId

它仅一次通过标准记录。在没有记录的情况下,我将联接更改为汇率,以LEFT-JOIN进行,因为我不知道可能(或没有)匹配的确切条件。在这种情况下,也许就是您的!=“ GBP”值/何时。

为帮助确保某些优化和交易量,我将在您的交易表上建立一个复合索引

( Status, Processing_Time, PaymentType, EntityID )

答案 2 :(得分:0)

我猜测性能会有所不同,因为INNER JOIN (JOIN)LEFT JOIN使用的表连接方式不同,并且它们对索引的影响也是如此。

首先查看EXPLAIN中的顺序。 您可以看到LEFT JOIN将以固定顺序(从左到右)联接表。 INNER JOIN-优化器将为您建立连接顺序(首先是小表)。 对于这两种情况,表key(在t1列表中)的EXPLAIN都是不同的。

它始终取决于表的结构,当连接顺序不同时,是否应用索引(正确的索引)。它甚至可以取决于例如不同的表排序规则。

看看这种方式,我希望它能有结果。