开发者

Very slow query with ORDER BY and LIMIT

开发者 https://www.devze.com 2023-02-15 16:18 出处:网络
I have a very slow query because using ORDER BY. Now i understand why it is slow but i have no idea how i make it faster.

I have a very slow query because using ORDER BY. Now i understand why it is slow but i have no idea how i make it faster.

The table got like 900.000 records. (the reason why it is slow)

SELECT SQL_NO_CACHE id, name 
FROM users where is_provider = 0 
AND activate开发者_运维百科d_at IS NOT NULL
AND is_ngo = 0 
AND deleted_at is NULL 
AND is_cancelled = 0   
ORDER BY name 
LIMIT 60000, 90;

I use limit because i use pagination. SQL_NO_CACHE because i dont want to use cache for testing.

This query takes like 60 seconds, which is way too long. It is a background task so if i can reduse it in 5 seconds it will be ok

I have indexes on the activated_at column and deleted_at which are time fields. The other ones are booleans so no indexes needed.

Thanks


I think indexing is the answer but you have to figure out the correct index for your query so you should try this:

EXPLAIN SELECT SQL_NO_CACHE id, name 
FROM users where is_provider = 0 
AND activated_at IS NOT NULL
AND is_ngo = 0 
AND deleted_at is NULL 
AND is_cancelled = 0   
ORDER BY name 
LIMIT 60000, 90;

As detailed thoroughly in this very old, but useful article:
http://www.databasejournal.com/features/mysql/article.php/1382791/Optimizing-MySQL-Queries-and-Indexes.htm


You may find this article helpful: http://www.mysqlperformanceblog.com/2006/09/01/order-by-limit-performance-optimization/

It deals with the combination of ORDER BY and LIMIT.


I would guess that it is the ordering by name that makes it slow.

To test, remove the ORDER clause and check how long it takes.

The name field probably should be indexed when you want to order by it.


I'd suggest adding an index on the most selective boolean field, i.e., if only 5% of the rows in the DB have is_provider = 0, then you can significantly cut down the number of rows you need to scan for the other properties. If the distribution is 50/50 there's not much point, but I'd look at the distributions and let that guide you in determining which indexes may be helpful. Of course, you should be guided by actual performance (including those on other queries you may have).


Is the name column indexed as a part of another index?

Ordering by an index should be relatively quick (no need for filesort), unless name happens to be a part of an index, and not the first part. See more here: http://dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html

Please post your EXPLAIN results so we can help further...


You can try

SELECT  * FROM (SELECT SQL_NO_CACHE id, name 
FROM users where is_provider = 0 
AND activated_at IS NOT NULL
AND is_ngo = 0 
AND deleted_at is NULL 
AND is_cancelled = 0   
ORDER BY name) t
LIMIT 60000, 90;

to avoid ORDER BY and LIMIT together.


The problem here is, Mysql is First trying to Order By all the Rows available in the table by Name and Then trying the Select the records basis the Where condition. So what you can try is First Select the records basis the Where Condition and run Order By name on result set.

Example:

SELECT  * FROM (SELECT SQL_NO_CACHE id, name 
FROM users where is_provider = 0 
AND activated_at IS NOT NULL
AND is_ngo = 0 
AND deleted_at is NULL 
AND is_cancelled = 0) t ORDER BY name
LIMIT 60000, 90;


ALternatively, remove the Order By clause and perform your ordering once you've read the records. It puts the work on the client, but that may be more reliable and faster if you database is slow (as it seems here).

Cheers,

Daniel

0

精彩评论

暂无评论...
验证码 换一张
取 消