Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two queries are fast separately, slow when joined as subqueries

Tags:

sql

mysql

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)."

like image 363
Jason Swett Avatar asked Apr 19 '11 13:04

Jason Swett


People also ask

Which query is faster subquery or JOIN?

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.

Why is subquery so slow?

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 .

How do you make subqueries run faster?

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.

Which is faster subquery or function?

using function (included that subquery) has better performance, when you define a function, the function will not run while calling the function.


1 Answers

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)
like image 116
Quassnoi Avatar answered Oct 21 '22 17:10

Quassnoi