如何在mysql中定义一个有100亿行的key/valuetable?

How to define a key/value table with 10 billion rows in mysql?

k  | v

k是一个唯一的字符串(varchar 32),v也是一个字符串(varchar 50),

我只会做这些查询:

insert into
select v from TABLE where k = "${k}"

我应该怎么写我的创作tablesql?

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

比如我应该用myisam还是innodb?

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

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

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

最重要的是簇键,'k' 是前导列,因为 WHERE 子句中的相等谓词。

如果'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 使用一个内部标识符作为集群键,并为我们的查询创建一个覆盖索引,由于内部标识符的开销,需要大约两倍的 space,以及单独的索引:

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

这几乎没有效率,但它确实允许重复和 NULL。同样,我们想要一个前导列为 k 的索引(因为 WHERE 子句中的相等谓词),并且还包括 v(使其成为覆盖索引),因此 SELECT可以从索引页面满足查询,而不需要在基础数据中查找页面 table.

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

假设启用innodb_file_per_table,我会考虑分区。这不会在查询性能方面有所改善,但这可以提高 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;