繁体   English   中英

如何提高大数据MYSQL查询的性能?

[英]How to improve the performance of MYSQL query with large data?

我正在使用具有以下数据的MySQL表:

users(ID, name, email, create_added) (about 10000 rows)
points(user_id, point) (about 15000 rows)

而我的查询:

SELECT u.*, SUM(p.point) point 
FROM users u 
LEFT JOIN points p ON p.user_id = u.ID 
WHERE u.id > 0 
GROUP BY u.id 
ORDER BY point DESC 
LIMIT 0, 10

我只获得前十名用户的最佳评价,但随后死亡。 如何提高查询性能?

就像@Grim所说的那样,可以使用INNER JOIN代替LEFT JOIN 但是,如果您真正寻求优化,我建议您为表users提供一个额外的字段,并预先计算point 在您当前的数据库设计中,该解决方案将击败任何查询优化。

LEFT JOIN INNER JOININNER JOIN 确保points.pointpoints.user_id进行索引。 我假设您可以摆脱WHERE子句,因为u.id始终大于0(尽管MySQL可能在查询优化阶段为您执行此操作)。

这实际上并不重要,因为您仅获得10行。 MySQL必须对每个用户的分数进行汇总,然后才能对它们进行排序(“使用文件排序”操作。)最后应用LIMIT。

覆盖索引ON points(user_id,point)将是最佳性能的最佳选择。 (我只是在猜测,没有任何EXPLAIN输出或表定义。)

usersid列可能是主键,或者至少是唯一索引。 因此,很可能您已经有一个id为开头的索引,如果是InnoDB,则为主键集群索引。)

我很想测试这样的查询:

 SELECT u.*
      , s.total_points
   FROM ( SELECT p.user_id
               , SUM(p.point) AS total_points
            FROM points p
           WHERE p.user_id > 0
           GROUP BY p.user_id
           ORDER BY total_points DESC
           LIMIT 10
        ) s
   JOIN user u
     ON u.id = s.user_id
  ORDER BY s.total_points DESC 

这确实会产生创建派生表的开销,但是要在点上具有适当的索引,并且必须使用user_id的前导列,并包括point列,MySQL可能可以通过使用索引来优化组,并避免使用“ filesort”操作(对于GROUP BY)。

该结果集上可能会执行“使用文件排序”操作,以获取按total_points排序的行。 然后从中获取前10行。

使用这10行,我们可以联接到用户表以获取相应的行。

但是,此结果略有不同,如果前十位中的user_id值不在用户表中,则该查询将返回少于10行。 (我希望有一个外键定义,所以不会发生,但是我只是在猜测没有表定义。)

一个EXPLAIN将显示正在使用由MySQL的访问计划。

有想过分区吗? 我目前正在使用大型数据库并成功改善sql查询。

例如,

PARTITION BY RANGE (`ID`) (
    PARTITION p1 VALUES LESS THAN (100) ENGINE = InnoDB,
    PARTITION p2 VALUES LESS THAN (200) ENGINE = InnoDB,
    PARTITION p3 VALUES LESS THAN (300) ENGINE = InnoDB,
    ... and so on..
)

它使我们在扫描mysql表时可以获得更好的速度。 即使表中有百万行,Mysql也只会扫描包含用户标识1到99的分区p 1。

看看这个http://dev.mysql.com/doc/refman/5.5/en/partitioning.html

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM