[英]optimizing query order by results to Using filesort;
查询:
SELECT
r.reply_id,
r.msg_id,
r.uid,
r.body,
r.date,
u.username as username,
u.profile_picture as profile_picture
FROM
pm_replies as r
LEFT JOIN users as u
ON u.uid = r.uid
WHERE
r.msg_id = '784351921943772258'
ORDER BY r.date DESC
我尝试了所有我能想到的索引组合,在google中搜索了如何最好地对它进行索引,但没有任何效果。
此查询对500个退回商品收取0.33的费用 ,并且还在计算 ...
说明:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE r ALL index1 NULL NULL NULL 540 Using where; Using filesort
1 SIMPLE u eq_ref uid uid 8 site.r.uid 1
显示创建pm_replies
CREATE TABLE `pm_replies` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`reply_id` bigint(20) NOT NULL,
`msg_id` bigint(20) NOT NULL,
`uid` bigint(20) NOT NULL,
`body` text COLLATE utf8_unicode_ci NOT NULL,
`date` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `index1` (`msg_id`,`date`,`uid`)
) ENGINE=MyISAM AUTO_INCREMENT=541 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
显示创建用户
CREATE TABLE `users` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`uid` bigint(20) NOT NULL,
`username` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`email` text CHARACTER SET latin1 NOT NULL,
`password` text CHARACTER SET latin1 NOT NULL,
`profile_picture` text COLLATE utf8_unicode_ci NOT NULL,
`date_registered` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uid` (`uid`),
UNIQUE KEY `username` (`username`)
) ENGINE=MyISAM AUTO_INCREMENT=2004 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
对于查询本身,最好的索引似乎是...
pm_replies: (msg_id, date, uid)
users: (uid)
重要的是pm_replies
。 您可以使用它来过滤数据(过滤列在第一),然后对数据排序(在排序列在第二)。
如果您删除过滤器,则情况会有所不同。 然后,您只想(date, uid)
作为索引。
索引中的最后一个字段只是使其对联接更友好,重要的部分实际上是users
的索引。
关于这一点,还有很多要说的,至少一本书要整整一章,如果您愿意的话可以多几本书。 但我希望这会有所帮助。
编辑
我建议的pm_replies
索引不是一个包含三个字段的索引,而不仅仅是三个索引。 这样可以确保索引中的所有条目都已按这些列进行了预排序。 这就像在Excel中按三列对数据进行排序。
具有三个单独的索引就像在三个选项卡上具有Excel数据一样。 每个按不同的字段排序。
只有在三个字段上建立一个索引,您才能得到这种行为...
-您可以选择一个具有相同msg_id的“记录”记录
-整个“束”彼此相邻,没有空隙等
-整个“束”按该msg_id的日期顺序排序
-对于具有相同日期的任何行,它们按user_id排序
(同样,user_id部分确实很小。)
请尝试以下方法:
SELECT
r.reply_id,
r.msg_id,
r.uid,
r.body,
r.date,
u.username as username,
u.profile_picture as profile_picture
FROM
pm_replies as r
LEFT JOIN users as u
ON (u.uid = r.uid AND r.msg_id = '784351921943772258')
ORDER BY r.date DESC
就我而言,它有帮助。
将日期添加到您的index1键,以便msg_id和date都在索引中。
看来优化器正在尝试通过ID强制索引以建立对用户表的联接。 由于您正在进行左联接(这没有意义,因为我希望每个条目都具有用户ID,因此是正常的INNER JOIN),因此我将其保持左联接。
因此,我将尝试以下方法。 根据MESSAGE ID和仅按其优缺点降序排列的日期查询排序,然后左联接,例如
SELECT
r.reply_id,
r.msg_id,
r.uid,
r.body,
r.date,
u.username as username,
u.profile_picture as profile_picture
FROM
( select R2.*
from pm_replies R2
where r2.msg_id = '784351921943772258' ) r
LEFT JOIN users as u
ON u.uid = r.uid
ORDER BY
r.date DESC
另外,由于我还没有MySQL,并且我不记得子查询中是否允许order by,如果可以,则可以优化内部预查询(使用别名“ R2”)并按在那里,因此它使用(msgid,date)索引并仅返回该集合...然后,联接到ID上的用户表,此时从源结果集中不需要索引,只需将用户表上的索引找到匹配。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.