MySQL 嵌套连接排序
Posted
技术标签:
【中文标题】MySQL 嵌套连接排序【英文标题】:MySQL nested join ordering 【发布时间】:2016-07-27 10:50:04 【问题描述】:我正在尝试获取按上次活动排序并分页的“活跃”用户列表。我最初将它用作基本连接,但是当我添加了几十万测试用户时,查询会随着分页而变得越来越长,并且在您到达最后一页时会花费绝对时间。
然后我嵌套连接以解决速度问题,但由于外部查询仅返回具有偏移量和限制的活动用户,然后才能应用订单,因此我无法正确排序结果。
这是当前查询;
$sql = "SELECT * FROM (
SELECT roles_users.*, users.last_active FROM roles_users, users
WHERE roles_users.role_id = '2'
LIMIT $offset, $limit
) AS role
LEFT JOIN users ON users.id = role.user_id
WHERE
users.f_name IS NOT NULL
AND users.city IS NOT NULL
AND users.gender IS NOT NULL
AND users.date_of_birth IS NOT NULL
ORDER BY users.last_active DESC";
这样做的最佳方法是什么,以使其高效运行并正确排序?
编辑
roles_users 的表结构;
#-- Field -- Type ----------- Null -- Key --- Foreign key --#
#
# user_id int(10) unsigned No primary users.id
# role_id int(10) unsigned No primary user_roles.id
#
#############################################################
users 表非常广泛,所以我不会放在这里。虽然它是相当标准的。
users.last_active 上有一个索引。
【问题讨论】:
注意LEFT JOIN y ... WHERE y ... [IS NOT NULL]
和INNER JOIN y ON...
一样
【参考方案1】:
(我无法清楚地理解你的查询。你能把表定义吗?)
这里有一些提示:
您的 ORDER BY/LIMIT 应该在顶部选择而不是在子选择中。
如果您想通过 order by/limit 在分页上实现稳定的查询时间,您必须使用索引进行 order by。
我认为您的请求可以很容易地重写为不使用子查询和/或您可以创建适当的索引。
如果您无法重写您的选择,请使用一个表格,您将每 N 分钟使用相应索引的查询结果填充一次表格,并使用该表格检索数据。也许物化视图可以解决问题。
https://dba.stackexchange.com/questions/86790/best-way-to-create-a-materialized-view-in-mysql
编辑:
SELECT roles_users.*, users.last_active FROM roles_users, users
WHERE users.id = role.user_id
AND roles_users.role_id = '2'
AND users.f_name IS NOT NULL
AND users.city IS NOT NULL
AND users.gender IS NOT NULL
AND users.date_of_birth IS NOT NULL
ORDER BY users.last_active DESC
LIMIT 0, 100
在 users.last_active 上创建索引
【讨论】:
我编辑了我的问题。 users.last_active 上已经有一个索引。您的查询几乎是我开始时的查询,运行查询以显示最后一页需要 46 秒。我正在尝试做的事情应该很简单,但由于某种原因似乎并非如此。 尝试不加入角色。几点了? 您可以存储 last_active 值的最后最小值以缩小范围 last_active 索引的基数是多少?以及行数? 抱歉问,因为我想确定:role_id 字段是否有单独的索引,或者至少在第一个索引列的字段中。以上是关于MySQL 嵌套连接排序的主要内容,如果未能解决你的问题,请参考以下文章