MySQL 对多个表进行排序需要很长时间

发布于 2024-11-08 20:20:18 字数 2669 浏览 0 评论 0原文

我有一个包含对象和相关表 object_info、object_theme(类别)、位置和对象所有者的表。

我想要的是首先显示优先级较高的对象所有者的所有对象,然后显示其余对象。因此,我的查询类似于以下内容:

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

如您所见,我选择所有对象,并为来自具有较高优先级状态的对象所有者的对象提供首先显示的边缘。然后从最低价开始排序。但大多数时候这个查询非常慢。

优化此查询的最佳步骤是什么?我尝试了各种索引,但瓶颈似乎是排序。当我把它拿出来时,查询速度就可以了。

(请注意,我没有加入主题(类别),我正在考虑以不同的方式实现这一点,因为您还需要对结果进行分组的 1:n 关系,这看起来非常慢。提到的所有其他表在连接中具有 1:1 关系。)。

比较一下:没有对两列进行排序的查询需要 0.0011 秒。上面提到的两列都是 0.8779。但根据负载的不同,甚至可能需要几秒钟。


带排序的解释:

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

不带排序的解释:

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

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 out 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

木落 2024-11-15 20:20:18

在 object_owner_priority 和 object_price 上定义索引,并将 where 子句更改为类似以下内容:

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

运气好的话应该可以解决问题。如果您已在 object_active 或 object_owner_active 上定义了索引,请考虑删除它们。

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.

人间☆小暴躁 2024-11-15 20:20:18

好吧,现在通过创建单独的订单列并通过 cron 作业填充它们来解决问题,该作业每隔一段时间执行一次慢速查询以生成所需的订单。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文