查询:
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
我尝试了所有可以想到的索引组合,在谷歌中搜索我如何能够将其编入索引,但没有任何效果。
此查询在 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
SHOW CREATE 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
答案 0 :(得分:5)
对于查询原样,最佳索引似乎是......
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部分非常小。)
答案 1 :(得分:0)
请试试这个:
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
就我而言,它有所帮助。
答案 2 :(得分:0)
将日期添加到index1键,以便msg_id和date都在索引中。
答案 3 :(得分:0)
Dems is saying应该是正确的,但是如果您使用InnoDB还有一个额外的细节:也许您正在支付secondary indexes on clustered tables的价格 - 实际上,通过二级索引访问行需要附加查询主要,即群集索引。这种“双重查找”可能会使索引对查询优化器的吸引力降低。
要缓解此问题,请尝试使用索引{/ 3>
pm_replies: (msg_id, date, uid, reply_id, body, date)
users: (uid, username, profile_picture)
答案 4 :(得分:0)
优化器似乎试图通过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)索引并返回该集合... THEN连接到ID上的用户表,在该点上从SOURCE结果集中不需要索引,只是该索引用户表来查找匹配。