Mechanizen
Mechanizen

Reputation: 109

Is it possible to further optimize this MySQL query?

I was running a query of this kind of query:

SELECT
-- fields
FROM
table1 JOIN table2 ON (table1.c1 = table.c1 OR table1.c2 = table2.c2)
WHERE
-- conditions

But the OR made it very slow so i split it into 2 queries:

SELECT
-- fields
FROM
table1 JOIN table2 ON table1.c1 = table.c1
WHERE
-- conditions

UNION 

SELECT
-- fields
FROM
table1 JOIN table2 ON table1.c2 = table.c2
WHERE
-- conditions

Which works much better but now i am going though the tables twice so i was wondering if there was any further optimizations for instance getting set of entries that satisfies the condition (table1.c1 = table.c1 OR table1.c2 = table2.c2) and then query on it. That would bring me back to the first thing i was doing but maybe there is another solution i don't have in mind. So is there anything more to do with it or is it already optimal?

Upvotes: 1

Views: 58

Answers (2)

Akina
Akina

Reputation: 42844

Test

SELECT
-- fields
FROM
table1 JOIN table2 ON table1.c1 = table2.c1
WHERE
-- conditions

UNION ALL

SELECT
-- fields
FROM
table1 JOIN table2 ON table1.c2 = table2.c2
WHERE
-- conditions
/* add one more condition which eliminates the rows selected by 1st subquery */
  AND table1.c1 != table2.c1

Copied from the comments:

Nico Haase > What do you mean by "test"?

OP shows query patterns only. So I cannot predict does the technique is effective or not, and I suggest OP to test my variant on his structure and data array.

Nico Haase > what you've changed

I have added one more condition to 2nd subquery - see added comment in the code.

Nico Haase > and why?

This replaces UNION DISTINCT with UNION ALL and eliminates combined rowset sorting for duplicates remove.

Upvotes: 1

The Impaler
The Impaler

Reputation: 48875

Splitting the query into two separate ones is usually better in MySQL since it rarely uses "Index OR" operation (Index Merge in MySQL lingo).

There are few items I would concentrate for further optimization, all related to indexing:

1. Filter the rows faster

The predicate in the WHERE clause should be optimized to retrieve the fewer number of rows. And, they should be analized in terms of selectivity to create indexes that can produce the data with the fewest filtering as possible (less reads).

2. Join access

Retrieving related rows should be optimized as well. According to selectivity you need to decide which table is more selective and use it as a driving table, and consider the other one as the nested loop table. Now, for the latter, you should create an index that will retrieve rows in an optimal way.

3. Covering Indexes

Last but not least, if your query is still slow, there's one more thing you can do: use covering indexes. That is, expand your indexes to include all the rows from the driving and/or secondary tables in them. This way the InnoDB engine won't need to read two indexes per table, but a single one.

Upvotes: 3

Related Questions