美文网首页
大表无索引前提下的查询和更新导致恐怖地全表扫描

大表无索引前提下的查询和更新导致恐怖地全表扫描

作者: 张广旭 | 来源:发表于2020-03-07 17:36 被阅读0次

统计日志数据库bingostat有一个gameplay表,用于记录玩家游戏行为。该表最近2个月(2020年1、2月)每月会积累200多万条记录。从游戏上线运营开始一共产生了1200多万条日志。使用的是PostgreSQL数据库。通常的说法是单表达到千万级记录就算大表了。PM向我反映查询该表响应速度变慢了。和表的记录数多有很大关系,同时跟查询语句也有关。做分表是最简单直接的优化查询效率的方式。
经过一番操作,完成了分表。原来的表有唯一索引,基于若干个字段创建 (pid, room_id, round_id, theme_id)。PostgreSQL分表之后,是不能创建唯一索引的。然后该表就没有创建任何索引。日志解析工具的实现代码中使用到了唯一索引,所以需要改代码。将日志写入gameplay表的逻辑是这样的:

  • 根据(pid, room_id, round_id, theme_id)查询是否有记录
  • 如果没有,就插入一条日志
  • 如果有,就根据(pid, room_id, round_id, theme_id)更新日志的某些字段

在实现细节上我还使用了事务。日志解析工具中只有一个线程基于同步I/O操作数据库。所以事务实际上是多余的。
部署了修改后的日志解析工具后,监控系统报警:统计数据库所在机器的CPU使用率多高。
日志解析工具是在机器A上解析日志,并写入机器B上的统计数据库。统计数据库的硬件配置是:两核CPU,4G内存。
监控系统显示:

  • CPU占有率持续处于高位。


    CPU占有率.jpg
  • 之前的系统负载一直在0.1以下,现在的负载达到4.5。


    系统平均负载.jpg

    我的第一反应是事务导致了CPU飙高。然后我去掉了日志解析工具中的多余的事务使用。再次部署后,发现CPU占有率依然居高不下。
    然后我想到索引的问题。原来有索引,现在没有索引。原来的代码使用到了索引相关的字段,现在的代码依然使用了索引相关的字段,也就是说涉及的SQL语句中的SELECT和UPDATE都带有WHERE子句。没有索引,会导致全表扫描。千万级记录数,全表扫描效率极低。我立即写了一个脚本给每一个分表创建了基于(pid, room_id, round_id, theme_id)四个字段的唯一索引,之后系统负载很快就回落到0.1以下。

相关文章

  • 大表无索引前提下的查询和更新导致恐怖地全表扫描

    统计日志数据库bingostat有一个gameplay表,用于记录玩家游戏行为。该表最近2个月(2020年1、2月...

  • mongo索引

       不使用索引的查询称为全表扫描。通常来说,应该尽量避免全表扫描,全表扫描的效率非常低。   创建索引: db....

  • 哪些情况会引起/要求全表扫描?

    一. 何时适用全表扫描(正面) 单表查询表很小,索引可能就比表还大;访问的数据占全表数据的百分比很大,索引访问的总...

  • MySQL索引设计分析

    1. 最简单的索引 假设查询id=4这条数据,在没有索引的前提下,只能全表扫描。 现在就需要针对主键设计一个索引,...

  • 数据库

    type类型 All:不用索引的全表扫描 index:使用索引的全表扫描 range:使用索引的范围扫描(记得使用...

  • 2019-01-10 Mysql 记录

    1.根据查询建立合适的索引(单字段索引和联合索引),不要只设置PRIMARY索引,查询其他字段时会进行全表扫描 2...

  • mongodb 索引详解

    索引能够提高数据库的查询效率,没有索引的话,查询会进行全表扫描(scan every document in...

  • 震惊,竟然不能命中索引?

    前言 数据库查询不走索引会导致全表扫描,效率低下。 举例 “列类型”与“where值类型”不符,不能命中索引,会导...

  • SQL-索引

    唯一索引、主键索引和聚集索引 A)索引可以避免全表扫描。多数查询可以仅扫描少量索引页及数据页,而不是遍历所有数据页...

  • MySQL索引的个人理解(详解)

    索引是查询优化最主要的方式; 查询方式: 一种是:全表扫描; 一种是:利用数据表上建立的所以进行扫描。 如:对表中...

网友评论

      本文标题:大表无索引前提下的查询和更新导致恐怖地全表扫描

      本文链接:https://www.haomeiwen.com/subject/joczrhtx.html