【问题标题】:MySQL, Two billion rows of data, read only, performance optimisations?MySQL,20 亿行数据,只读,性能优化?
【发布时间】:2013-08-17 02:55:14
【问题描述】:

我有一组整数数据。第一个是数字 0,最后一个是 47055833459。从第一个到最后一个数字有 20 亿个,它们永远不会改变或添加。唯一插入 mysql 表的方法是将这些数据加载到其中。从那时起,它只会被读取。

我预测数据库表的大小约为 20Gb。我计划有两列:

id, data

Id 将是一个主键,自动递增 unsigned INT,data 将是一个 unsigned BIGINT

优化这两列只读数据的最佳方法是什么?我查看了其他类似的问题,但它们都考虑了写入速度和不断增加的表格。我使用的主机不支持 MySQL 分区,所以不幸的是,目前这不是一个选项。如果事实证明分区是唯一的方法,那么我将重新考虑一个新的主机。

该表只会被 id 列访问,因此数据列不需要索引。

总而言之,在 MySQL 中处理具有 20 亿行和两列的表的最佳方法是什么?没有分区,针对读取进行了优化?

【问题讨论】:

  • 您在数据上运行什么样的查询?
  • 唯一会在表上运行的查询是:“SELECT id, data FROM table WHERE id = $id LIMIT 1”,数据库用户也将被限制为只能选择
  • 我认为您不需要limit 1。将id 声明为主键足以满足您的目的。
  • id 是为了在这个集合上表达某种有意义的顺序吗?或者它只是一个无意义的标识符,它从输入数字的顺序中获取它的顺序。
  • 将 id 作为外键存储在别处而不是仅仅存储 BIGINT 本身的副本有什么好处?

标签: mysql optimization database-design query-optimization database-performance


【解决方案1】:

假设您使用的是 InnnDB,您应该:

CREATE TABLE T (
    ID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    DATA BIGINT UNSIGNED
);

这将有效地创建一个大 B-Tree 而没有其他任何东西,并且通过 ID 检索一行可以在单个索引查找中完成1。请查看"Understanding InnoDB clustered indexes" 了解更多信息。


1 没有表堆访问,实际上根本就没有堆。

【讨论】:

    【解决方案2】:

    像这样定义你的表。

    CREATE TABLE `lkup` (
      `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
      `data` BIGINT UNSIGNED NOT NULL,
      PRIMARY KEY (`id`, `data`)
    ) 
    

    复合主键会占用磁盘空间,但查找速度会非常快;只需读取索引(称为覆盖索引)即可满足您的查询。

    当您完成将静态数据加载到其中时,请执行OPTIMIZE TABLE lkup。这可能需要一段时间,但它会在运行时获得巨大回报。

    【讨论】:

    • 编辑删除冗余索引,使主键成为覆盖索引。
    • 假设 InnoDB,PRIMARY KEY (id) 也涵盖了查询,这是集群工作方式的结果。此外,PRIMARY KEY (id, data) 会损害数据完整性(允许重复 ID)。
    • 我怀疑AUTO_INCREMENT 是需要的。听起来他非常小心地挑选了他的 20 亿个 ID(从集合 [0, 47055833459] 中)。
    • 我使用 auto_increment 的原因是因为我将分块加载数据,而不是手动插入 ID,我想我会把它留给 MySQL。插入 20 亿行后,如果有助于提高性能,我可以删除 AUTO_INCREMENT 属性。自动增量会大大提高读取性能吗?
    猜你喜欢
    • 2012-04-06
    • 1970-01-01
    • 2011-06-14
    • 2016-01-24
    • 1970-01-01
    • 2019-08-23
    • 2014-07-24
    • 2011-02-18
    • 2019-12-28
    相关资源
    最近更新 更多