Why is this INNER JOIN/ORDER BY mysql query so slow?

一世执手 提交于 2019-12-11 13:07:55

问题


I have very big database of customers. This query was ok before I added ORDER BY. How can I optimize my query speed?

$sql = "SELECT * FROM customers 
LEFT JOIN ids ON customer_ids.customer_id = customers.customer_id AND ids.type = '10'
ORDER BY customers.name LIMIT 10";

ids.type and customers.name are my indexes

Explain query

id  select_type  table      type    possible_keys   key     key_len     ref     rows    Extra   
1   SIMPLE       customers  ALL     NULL            NULL    NULL        NULL    955     Using temporary; Using filesort
1   SIMPLE       ids        ALL     type            NULL    NULL        NULL    3551    Using where; Using join buffer (Block Nested Loop)

回答1:


(I assume you meant to type ids.customer_id = customer.customer_id and not customer_ids.customer_id)

Without the ORDER BY mysql grabbed the first 10 ids of type 10 (indexed), looked up the customer for them, and was done. (Note that the LEFT JOIN here is really an INNER JOIN because the join conditions will only hold for rows that have a match in both tables)

With the ORDER BY mysql is probably retrieving all type=10 customers then sorting them by first name to find the first 10.

You could speed this up by either denormalizing the customers table (copy the type into the customer record) or creating a mapping table to hold the customer_id, name, type tuples. In either case, add an index on (type, name). If using the mapping table, use it to do a 3-way join with customers and ids.

If type=10 is reasonably common, you could also force the query to walk the customers table by name and check the type for each with STRAIGHT JOIN. It won't be as fast as a compound index, but it will be faster than pulling up all matches.

And as suggested above, run an EXPLAIN on your query to see the query plan that mysql is using.




回答2:


LEFT is the problem. By saying LEFT JOIN, you are implying that some customers may not have a corresponding row(s) in ids. And you are willing to accept NULLs for the fields in place of such an ids row.

If that is not the case, then remove LEFT. Then make sure you have an index on ids that starts with type. Also, customers must have an index (probably the PRIMARY KEY) starting with customer_id. With those, the optimizer can start with ids, filter on type earlier, thereby have less work to do.

But, still, it must collect lots of rows before doing the sort (ORDER BY); only then can it deliver the 10 (LIMIT).

While you are at it, add INDEX(customer_id) to ids -- that is what is killing performance for the LEFT version.



来源:https://stackoverflow.com/questions/28390181/why-is-this-inner-join-order-by-mysql-query-so-slow

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!