简体   繁体   中英

How to make query faster with group by and order by

I have large table with 615 million records in items and 10 thousand in markets

the below query takes 5+ seconds to execute

how can I make it faster. ?

SELECT items.name,items.ID as itemID,items.market_id as market_id,markets.name as marketname 
from items,markets 
where markets.ID = items.market_id and 
items.name like '%bab%' 
group by items.name 
order by items.name ASC 
limit 0,10

Explain

在此处输入图像描述

-> Limit: 10 row(s)  (actual time=4657.094..4657.096 rows=9 loops=1)

-> Sort: items.`name`, limit input to 10 row(s) per chunk  (actual time=4657.093..4657.094 rows=9 loops=1)

-> Table scan on <temporary>  (actual time=0.002..0.003 rows=9 loops=1)

-> Temporary table with deduplication  (cost=1141592.47 rows=625722) 
(actual time=4657.070..4657.072 rows=9 loops=1)

-> Nested loop inner join  (cost=1141592.47 rows=625722) (actual time=0.056..4541.471 rows=85329 loops=1)

-> Filter: (items.`name` like \'%bab%\')  (cost=593647.14 rows=625722) (actual time=0.043..4456.394 rows=85329 loops=1)

-> Table scan on items  (cost=593647.14 rows=5632061) (actual time=0.037..2864.754 rows=6153656 loops=1)

-> Single-row index lookup on markets using PRIMARY (ID=items.market_id)  (cost=0.78 rows=1) (actual time=0.001..0.001 rows=1 loops=85329)

You might get a (small?,) improvement: when you do this:

SELECT items.name,items.ID as itemID,items.market_id as market_id,markets.name as marketname 
from items
inner join markets on markets.ID = items.market_id
where markets.ID IN (SELECT items.market_id 
                     FROM marketd
                     WHERE items.name like '%bab%' 
                     order by items.name ASC 
                     limit 0,10)
order by items.name

EDIT: oops, that's tru you cannot do LIMIT in a subquery....

If you have MySQL 8.0+, you can do:

WITH cte AS (
   SELECT items.market_id 
   FROM marketd
   WHERE items.name like '%bab%' 
   order by items.name ASC 
   limit 0,10
)
SELECT items.name,items.ID as itemID,items.market_id as market_id,markets.name as marketname 
from items
inner join markets on markets.ID = items.market_id
where markets.ID IN ( SELECT market_id 
                      FROM cte )
order by items.name;

also, you might need to add an index on market_id , if that does not exists yet. With that, the cte will use that index.

This should work with any version of MySQL at least since 5.0:

SELECT items.name,
       items.ID as itemID,
       items.market_id as market_id,
       ( SELECT markets.name 
              FROM markets WHERE markets.ID = items.market_id
       ) as marketname 
    FROM items
    WHERE items.name like '%bab%' 
    ORDER BY items.name ASC 
    LIMIT 10

That should eliminate the GROUP BY .

Indexes:

items:  (name, ID, market_id)
markets:  presumably `ID` is the PRIMARY KEY

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM