Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimizing for an OR in a Join in MySQL

Tags:

sql

mysql

I've got a pretty complex query in MySQL that slows down drastically when one of the joins is done using an OR. How can I speed this up? the relevant join is:

LEFT OUTER JOIN publications p ON p.id = virtual_performances.publication_id 
                               OR p.shoot_id = shoots.id

Removing either condition in the OR decreases the query time from 1.5s to 0.1s. There are already indexes on all the relevant columns I can think of. Any ideas? The columns in use all have indexes on them. Using EXPLAIN I've discovered that once the OR comes into play MySQL ends up not using any of the indexes. Is there a special kind of index I can make that it will use?

like image 363
Andrew Cholakian Avatar asked Dec 23 '22 08:12

Andrew Cholakian


1 Answers

This is a common difficulty with MySQL. Using OR baffles the optimizer because it doesn't know how to use an index to find a row where either condition is true.

I'll try to explain: Suppose I ask you to search a telephone book and find every person whose last name is 'Thomas' OR whose first name is 'Thomas'. Even though the telephone book is essentially an index, you don't benefit from it -- you have to search through page by page because it's not sorted by first name.

Keep in mind that in MySQL, any instance of a table in a given query can make use of only one index, even if you have defined multiple indexes in that table. A different query on that same table may use another index if the optimizer reasons that it's more helpful.

One technique people have used to help in situations like your is to do a UNION of two simpler queries that each make use of separate indexes:

 SELECT ...
 FROM virtual_performances v
 JOIN shoots s ON (...)
 LEFT OUTER JOIN publications p ON (p.id = v.publication_id)
UNION ALL
 SELECT ...
 FROM virtual_performances v
 JOIN shoots s ON (...)
 LEFT OUTER JOIN publications p ON p.shoot_id = s.id;
like image 121
Bill Karwin Avatar answered Jan 02 '23 16:01

Bill Karwin