开发者

MySQL sorting over multiple tables takes very long

开发者 https://www.devze.com 2023-03-07 10:20 出处:网络
I have a table with objects and related tables object_info, object_theme (category), locations and the object owners.

I have a table with objects and related tables object_info, object_theme (category), locations and the object owners.

What I want is showing all objects from object owners with a higher priority first, and then the rest. So my query is something like the following:

SELECT 
   (...)
FROM objects
INNER JOIN object_info ...
INNER JOIN objectowner_info ...
INNER JOIN locations ...
WHERE object_active = 1
  AND object_owner_active = 1
ORDER BY object_owner_priority DESC,
         object_price ASC
   LIMIT 0, 10

As you can see I select all objects and giving the ones from object owners with a higher priority status the edge of showing first. And then sorting from lowest price up. But most of the time this query is extremely slow.

What are the best steps to optimize this query? I've tried all sorts of indexes, but the bottleneck seems to be the sorting. When I take that o开发者_如何学Cut the query is OK speed-wise.

(Please note I didn't join the themes (categories), I'm thinking of implementing this differently because of the 1:n relations you'll need to group the result as well, and that seems awfully slow. All other tables mentioned in the join have a 1:1 relationship.).

To compare: a query without both columns in sorting takes 0.0011 seconds. The one mentioned above with both columns 0.8779. But depending on the load it could take even seconds.


EXPLAIN with sorting:

id  select_type     table   type    possible_keys                                       key                 key_len     ref             rows    Extra
1   SIMPLE          o       ALL     PRIMARY,fk_object_user,fk_object_city,type active   NULL                NULL        NULL            63773   Using where; Using temporary; Using filesort
1   SIMPLE          ooi     ref     fk_objectowner_id                                   fk_objectowner_id   4           o.object_user   1       Using where
1   SIMPLE          oo      eq_ref  PRIMARY,id_and_status                               PRIMARY             4           o.object_user   1       Using where
1   SIMPLE          l       eq_ref  PRIMARY                                             PRIMARY             4           o.object_city   1       Using where
1   SIMPLE          oi      ref     fk_info_lang,fk_info_object,lang_object             fk_info_object      3           o.object_id     1       Using where

EXPLAIN without sorting:

id  select_type     table   type    possible_keys                                       key                 key_len     ref             rows    Extra
1   SIMPLE          o       ALL     PRIMARY,fk_object_user,fk_object_city,type active   NULL                NULL        NULL            63773   Using where
1   SIMPLE          ooi     ref     fk_objectowner_id                                   fk_objectowner_id   4           o.object_user   1   Using where
1   SIMPLE          oo      eq_ref  PRIMARY,id_and_status                               PRIMARY             4           o.object_user   1   Using where
1   SIMPLE          l       eq_ref  PRIMARY                                             PRIMARY             4           o.object_city   1   Using where
1   SIMPLE          oi      ref     fk_info_lang,fk_info_object,lang_object             fk_info_object      3           o.object_id     1   Using where


Define indexes on object_owner_priority and object_price, and change the where clause to something like:

WHERE object_active + 0 = 1
  AND object_owner_active + 0 = 1

With any luck that should do the trick. If you have defined indexes on object_active or object_owner_active, consider deleting them.


Well, problem is now solved by creating separate order columns and filling them through a cron job that executes the slow query every once-in-a-while to generate the wanted order.

0

精彩评论

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