这个查询有什么问题(选择...在哪里(选择...)?

时间:2009-12-30 15:48:43

标签: mysql select

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

6 个答案:

答案 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'

它做同样的