iplist table (id,username,ip,created) - 存储每个用户的不同IP地址
我想找到所有与'angryuser'具有相同IP地址的用户名
MySQL QUERY:
SELECT username,
ip
FROM `iplist`
WHERE ip IN (
SELECT ip
FROM iplist
WHERE username='angryuser'
)
如果我运行此查询,它会进入循环并杀死我的服务器:)
为什么?
更新
这是执行计划:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY iplist ALL NULL NULL NULL NULL 102757 Using where
2 DEPENDENT SUBQUERY iplist ALL NULL NULL NULL NULL 102757 Using where
答案 0 :(得分:4)
您是否尝试过正常的 INNER JOIN
SELECT p.username,
p.ip
FROM iplist p INNER JOIN
iplist s ON p.ip = s.ip
WHERE s.username='angryuser'
确保您在表格中具有正确的索引,如前所述。
答案 1 :(得分:1)
好吧,查询运行正常。这里最有可能是另一个问题。你的桌子上有没有索引,你的桌子有多大?
答案 2 :(得分:1)
有关原始子查询执行速度慢于加入的原因,请参阅:http://dev.mysql.com/doc/refman/5.0/en/subquery-restrictions.html
答案 3 :(得分:0)
您需要在(ip, username)
MySQL
尝试将您的查询优化为:
SELECT ip, username
FROM iplist ui
WHERE EXISTS
(
SELECT NULL
FROM iplist uo
WHERE uo.username = 'angry'
AND uo.id = ui.id
)
如果您创建此索引,内部EXISTS
(需要对用户的每一行进行评估)只需要一次索引扫描。
但是,最好像这样重写查询:
SELECT io.username, io.ip
FROM iplist ia
JOIN iplist io
ON io.ip = ia.ip
WHERE ia.username = 'angryuser'
AND io.username <> 'angryuser'
这样,'angryuser'
查询将成为领先者,引擎只需要检查几个IPs
。
您应该创建(ip, username)
的索引,以便快速开始工作。
<强>更新强>
如果您的用户名太长,则需要创建一个带前缀的索引:
CREATE INDEX ix_iplist_ip_username ON (ip, username (30))
30
个字符足以让这个索引具有选择性。
答案 4 :(得分:0)
可能是因为子查询返回了一个大的结果集:
SELECT ip
FROM iplist
WHERE username='angryuser'
答案 5 :(得分:-1)
为什么不使用:
SELECT username, ip FROM iplist WHERE username='angryuser'
它做同样的