【问题标题】:MySQL - help for a performant queryMySQL - 高性能查询的帮助
【发布时间】:2013-03-19 02:30:03
【问题描述】:

我有一张表,我在其中存储了我网站的所有登录信息。结构如下:

TABLE users_logins

loginid INT UNSIGNED AUTO_INCREMENT PRIMARY KEY
userid INT
iplogin VARCHAR(15)
logindate datetime

现在,我需要一个查询来检索使用相同 IP 进行首次登录的用户数量。结果应该是这样的:

iplogin | numberofaccounts

正如我之前所说,“numberofaccounts”是第一次使用相同“iplogin”登录的用户数。

该表有大约 300k 行......那么我应该怎么做才能获得我需要的良好性能?

谢谢,

L.

【问题讨论】:

  • 定义“良好的性能”。只有 300k 行,除非您将 486 用于服务器,否则这真的无关紧要。
  • 表格中有多少个不同的用户 (distinct user_id)?又有多少个不同的ip?
  • @ypercube 不多,35k 左右

标签: mysql performance greatest-n-per-group


【解决方案1】:

添加这些索引:

alter table users_logins 
  add key (iplogin, userid, logindate),
  add key (userid, logindate);

现在演示您可以通过查找同一用户没有其他早期登录的登录来执行查询以获取每个用户的最早登录。

这是一种常见的解决方案,可以让每个用户获得最大/最早的条目或其他任何内容。

select t1.iplogin, count(*) as numberofaccounts 
from users_logins as t1 
left outer join users_logins as t2 
  on (t1.userid=t2.userid and t1.logindate > t2.logindate) 
where t2.userid is null 
group by iplogin\G

上面定义的索引有助于LEFT OUTER JOINGROUP BY

EXPLAIN 报告显示这已得到很好的优化。它对两个表都使用了索引,并且不会导致临时表或文件排序,这通常是性能杀手。

它会进行索引扫描 (type: index),这意味着它会读取整个索引,但至少这不是表扫描。

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: index
possible_keys: iplogin
          key: iplogin
      key_len: 29
          ref: NULL
         rows: 1
     filtered: 100.00
        Extra: Using index
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: t2
   partitions: NULL
         type: ref
possible_keys: userid
          key: userid
      key_len: 5
          ref: test.t1.userid
         rows: 1
     filtered: 100.00
        Extra: Using where

【讨论】:

    【解决方案2】:

    我只是为您的用户表中的第一个登录 ip 添加一列。然后就很简单了

    select count(*), firstip 
    from users 
    group by firstip
    

    【讨论】:

    • 是的,我同意 Tyler 的观点,我已经在考虑过了,但不幸的是,目前无法选择编辑结构。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多