MySQL 对多个表进行排序需要很长时间
我有一个包含对象和相关表 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 object_owner_priority 和 object_price 上定义索引,并将 where 子句更改为类似以下内容:
运气好的话应该可以解决问题。如果您已在 object_active 或 object_owner_active 上定义了索引,请考虑删除它们。
Define indexes on object_owner_priority and object_price, and change the where clause to something like:
With any luck that should do the trick. If you have defined indexes on object_active or object_owner_active, consider deleting them.
好吧,现在通过创建单独的订单列并通过 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.