I have two queries that each, on their own, run pretty quickly (less than 2 seconds). However, when I try to join them as subqueries, it runs ridiculously slowly. The last time I ran it it took about 68 seconds. Here's the full query:
SELECT t.count,
t.total
FROM (SELECT t.account_number,
COUNT(t.id) count,
SUM(t.amount) total,
ib.id import_bundle_id
FROM import_bundle ib
JOIN generic_import gi ON gi.import_bundle_id = ib.id
JOIN transaction_import ti ON ti.generic_import_id = gi.id
JOIN account_transaction t ON t.transaction_import_id = ti.id
JOIN transaction_code tc ON t.transaction_code_id = tc.id
WHERE tc.code IN (0, 20, 40)
GROUP BY t.account_number) t
JOIN (SELECT a.account_number,
np.code
FROM import_bundle ib
JOIN generic_import gi ON gi.import_bundle_id = ib.id
JOIN account_import ai ON ai.generic_import_id = gi.id
JOIN account a ON a.account_import_id = ai.id
JOIN account_northway_product anp ON anp.account_id = a.id
JOIN northway_product np ON anp.northway_product_id = np.id
WHERE np.code != 'O1') a ON t.account_number = a.account_number
That this query should run slowly is not a total surprise. If these were two separate tables and not subqueries, I would put indexes on their account_number
columns. However, it's obviously not possible to put indexes on query results, so I can't do that. I suspect that's part of the problem.
Aside from that, I don't understand why the query is slow and I don't have any ideas on how to speed it up, other than adding two summary tables, which I don't want to do if I don't have to.
By the way, this query in English might be, "Get all the POS transactions (codes 0, 20 and 40) for accounts that aren't overdraft protection accounts (code O1)."
Advantages Of Joins:The retrieval time of the query using joins almost always will be faster than that of a subquery. By using joins, you can maximize the calculation burden on the database i.e., instead of multiple queries using one join query.
For multiple-table subqueries, execution of NULL IN (SELECT ...) is particularly slow because the join optimizer does not optimize for the case where the outer expression is NULL .
The most obvious way to make a subquery run fast is to ensure that it is supported by an index. Ideally, we should create a concatenated index that includes every column referenced within the subquery. We can see from the following EXPLAIN output that MySQL makes use of the index to resolve the subquery.
using function (included that subquery) has better performance, when you define a function, the function will not run while calling the function.
Put the check into the main query:
SELECT t.account_number,
COUNT(t.id) count,
SUM(t.amount) total,
ib.id import_bundle_id
FROM transaction_code tc
JOIN account_transaction t
ON t.transaction_code_id = tc.id
JOIN transaction_import ti
ON ti.id = t.transaction_import_id
JOIN generic_import gi
ON gi.id = ti.generic_import_id
JOIN import_bundle ib
ON ib.id = gi.import_bundle_id
WHERE tc.code IN (0, 20, 40)
AND t.account_number NOT IN
(
SELECT anp.id
FROM account_northway_product anp
JOIN northway_product np
ON np.id = anp.northway_product_id
WHERE np.code = '01'
)
GROUP BY
t.account_number
Create the following indexes:
transaction_code (code)
account_transaction (transaction_code_id)
account_transaction (account_number)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With