4

I have a MyISAM Table with circa 1 million rows.

SELECT * FROM table WHERE colA='ABC' AND (colB='123' OR colC='123');

The query above takes over 10 seconds to run. All columns in question are indexed.

But when I split it as follows...

SELECT * FROM table WHERE colA='ABC' AND colB='123';
SELECT * FROM table WHERE colA='ABC' AND colC='123';

Each individual query takes 0.002 seconds.

What gives, and how do I optimize the table/query?

R C
  • 441
  • 4
  • 10

1 Answers1

0
( SELECT * FROM table WHERE colA='ABC' AND colB='123' )
UNION DISTINCT
( SELECT * FROM table WHERE colA='ABC' AND colC='123' )
;

And have

INDEX(colA, colB),
INDEX(colA, colC)

You should consider moving to InnoDB, though it may not matter to this particular question.

Here's how the UNION will work:

  1. Perform each SELECT. They will be very efficient due to the indexes suggested.
  2. Collect the results in a tmp table.
  3. De-dup the temp table and deliver the resulting rows.

All the rows are 'touched' in the original query (with OR).

With the UNION:

  1. Only the necessary rows are touched in the SELECTs.
  2. Those rows are written to the tmp table.
  3. Those rows are reread. (The de-dupping may involve touching the rows more than once.)
Rick James
  • 135,179
  • 13
  • 127
  • 222
  • Have you got any idea of why using OR is **that much** slower ? – Brewal Apr 26 '18 at 02:37
  • 1
    MySQL won't be able to use the relevant indexes with the original OR condition. Therefore, in many cases when you split the condition to a UNION, MySQL will be able to use the indexes, as you're left with only AND conditions, without OR conditions. Look into the EXPLAIN of both options and you'll see the difference right away. – Tomer Shay Apr 26 '18 at 12:20
  • 1
    @Brewal - "arbitrarily" slower. If the table has a million rows and only a few are needed, it may be 1000x slower. On a smaller table, where you need most rows, it could even be faster. The timings that you gave lead me to guess that the `UNION` might take 0.03s; that is, 300x. – Rick James Apr 26 '18 at 21:03