如何在mysql中定义一个包含100亿行的键/值表?

时间:2017-02-23 00:08:54

标签: mysql sql mariadb

k

v是一个唯一的字符串(varchar 32),insert into select v from TABLE where k = "${k}" 也是一个字符串(varchar 50),

我只会做这些查询:

{{1}}

我该如何编写我的create table sql?

喜欢mysql中的分区?我应该用吗?

例如,我应该使用myisam还是innodb?

我有很多读取,很少插入,所以行级锁定InnoDB可能适合吗?

1 个答案:

答案 0 :(得分:1)

这是一个测试问题吗?假设我们不允许NULL值,并且我们不允许重复,我会选择索引组织表:

CREATE TABLE mytable 
( k  VARCHAR(32) NOT NULL COMMENT 'pk (cluster key), ...'
, v  VARCHAR(50) NOT NULL COMMENT 'pk (cluster key), ...'
, PRIMARY KEY (k,v)
) ENGINE=InnoDB

最重要的是群集密钥,由于WHERE子句中的等式谓词,因此'k'是前导列。

如果'k'保证是唯一的,那么它就可以作为PRIMARY KEY。

CREATE TABLE mytable 
( k  VARCHAR(32) NOT NULL COMMENT 'pk (cluster key), ...'
, v  VARCHAR(50) NOT NULL COMMENT '...'
, PRIMARY KEY (k)
) ENGINE=InnoDB

这将阻止INSERT创建具有重复值'k'的行。

在最坏的情况下,如果关于可空性和唯一性的假设无效,那么在提供群集密钥方面我们处于一个受损的世界。我们可以让InnoDB使用内部标识符作为集群密钥,只需为我们的查询创建覆盖索引,由于内部标识符的开销和单独的索引,需要大约两倍的空间:

CREATE TABLE mytable 
( k  VARCHAR(32) COMMENT ''
, v  VARCHAR(50) COMMENT ''
, KEY mytable_IX1 (k,v)
) ENGINE=InnoDB

这不是那么有效,但它确实允许重复和NULL。同样,我们想要一个前导列为k的索引(由于WHERE子句中的等式谓词),还包括v(使其成为覆盖索引),因此可以满足SELECT查询从索引页面,无需在基础数据表中查找页面。

MySQL支持InnoDB以外的存储引擎。这是我们最好的猜测,没有关于群集,复制等的任何其他规范。

假设innodb_file_per_table已启用,我会考虑进行分区。这不会在查询性能方面发挥作用,但这可以提高表的可管理性,例如,如果我们想要或需要重新组织

  PARTITION BY RANGE (k) 
  ( PARTITION ke VALUES LESS THAN ('e')
  , PARTITION ki VALUES LESS THAN ('i')
  , PARTITION ko VALUES LESS THAN ('o')
  , PARTITION ku VALUES LESS THAN ('u')
  , PARTITION kz VALUES LESS THAN ('z')
  , PARTITION px VALUES LESS MAXVALUE
  )

然后我们可以一次重新组织一个分区:

  ALTER TABLE mytable REBUILD PARTITION ko;