【发布时间】:2009-09-06 22:41:08
【问题描述】:
我有一个 mysql 查询,它获取用户是发送者或接收者的私人消息列表。
SELECT
users_user1.user_name AS pm_username_1,
users_user1.user_avatar AS pm_username_1_avatar,
users_user2.user_name AS pm_username_2,
users_user2.user_avatar AS pm_username_2_avatar,
pms.*
FROM pm pms
LEFT JOIN users users_user1
ON users_user1.user_id = pms.pm_sender
LEFT JOIN users users_user2
ON users_user2.user_id = pms.pm_receiver
WHERE pm_thread = pm_id
AND (pm_receiver = '1' OR pm_sender = '1')
AND pm_delete != '1'
ORDER by pm_thread_last DESC LIMIT 0, 15
问题是……据我所知……它不能使用任何索引。
有什么办法可以解决这个问题?
编辑
+----+-------------+-------------+--------+---------------+---------+---------+------------------------+-------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+--------+---------------+---------+---------+------------------------+-------+-----------------------------+
| 1 | SIMPLE | pms | ALL | pm_receiver | NULL | NULL | NULL | 25354 | Using where; Using filesort |
| 1 | SIMPLE | users_user1 | eq_ref | PRIMARY | PRIMARY | 4 | movies.pms.pm_sender | 1 | |
| 1 | SIMPLE | users_user2 | eq_ref | PRIMARY | PRIMARY | 4 | movies.pms.pm_receiver | 1 | |
+----+-------------+-------------+--------+---------------+---------+---------+------------------------+-------+-----------------------------+
将架构更改为:
(SELECT
users_user1.user_name AS pm_username_1,
users_user1.user_avatar AS pm_username_1_avatar,
users_user2.user_name AS pm_username_2,
users_user2.user_avatar AS pm_username_2_avatar,
pms.*
FROM pm pms
LEFT JOIN users users_user1
ON users_user1.user_id = pms.pm_sender
LEFT JOIN users users_user2
ON users_user2.user_id = pms.pm_receiver
WHERE pm_thread = pm_id
AND (pm_receiver = '1')
AND pm_delete != '1')
UNION
(SELECT
users_user1.user_name AS pm_username_1,
users_user1.user_avatar AS pm_username_1_avatar,
users_user2.user_name AS pm_username_2,
users_user2.user_avatar AS pm_username_2_avatar,
pms.*
FROM pm pms
LEFT JOIN users users_user1
ON users_user1.user_id = pms.pm_sender
LEFT JOIN users users_user2
ON users_user2.user_id = pms.pm_receiver
WHERE pm_thread = pm_id
AND (pm_sender = '1')
AND pm_delete != '1')
ORDER by pm_thread_last DESC LIMIT 0, 15
解释
+----+--------------+-------------+--------+---------------+-------------+---------+------------------------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+-------------+--------+---------------+-------------+---------+------------------------+------+----------------+
| 1 | PRIMARY | pms | ref | pm_receiver | pm_receiver | 4 | const | 336 | Using where |
| 1 | PRIMARY | users_user1 | eq_ref | PRIMARY | PRIMARY | 4 | movies.pms.pm_sender | 1 | |
| 1 | PRIMARY | users_user2 | eq_ref | PRIMARY | PRIMARY | 4 | movies.pms.pm_receiver | 1 | |
| 2 | UNION | pms | ref | pm_sender | pm_sender | 4 | const | 283 | Using where |
| 2 | UNION | users_user1 | eq_ref | PRIMARY | PRIMARY | 4 | movies.pms.pm_sender | 1 | |
| 2 | UNION | users_user2 | eq_ref | PRIMARY | PRIMARY | 4 | movies.pms.pm_receiver | 1 | |
| NULL | UNION RESULT | <union1,2> | ALL | NULL | NULL | NULL | NULL | NULL | Using filesort |
+----+--------------+-------------+--------+---------------+-------------+---------+------------------------+------+----------------+
【问题讨论】:
-
在查询中发布 EXPLAIN 的输出。 (并不是说如果表很小,mysql 可能不会使用索引 - 扫描可能同样快。)
-
嘿,你为什么把 1337 改成 1?抱怨:当您更改问题数据时,很难写出问题的答案。