索引基于网格的数据的最有效(或有意义)的方法

hex*_*rot 4 mysql primary-key index-tuning

我有一个 MySQL 表,我希望它有几百万行和 99% 的选择语句。我遇到的问题是想出一种有意义的方法来确定主键。(我在底部提供了一个表格转储以供参考)

对于某些背景,我正在使用二维网格,其范围在每个方向上从大约 -800000 到 +800000 不等。每行由其 X/Z 坐标标识,每个坐标可能有 1-30 个相关的位串(类型)。

我的顾虑是:

1)我缺乏一种有意义的方法来主键这个表。虽然我知道我可以id使用 auto_increment创建一个字段,但我知道实际上这个键永远不会被使用,因为100%的 SELECTS 将采用以下形式:

SELECT `type`, `offset`, `bitstring` WHERE `x` = 0 AND `z` = 0;
Run Code Online (Sandbox Code Playgroud)

2)我打算通过以下方式在多列(逻辑x/z)上建立索引:

CREATE INDEX coordinate ON bitstrings(x, z)
Run Code Online (Sandbox Code Playgroud)

虽然我觉得这恰当地解决了我在现实世界中的选择,但我一直担心它是索引不足,基于数十个帖子说“是的,你需要一个 PK”。这是一种可以忽略 PK 的情况,还是任意的id最终仍会提供一些非常值得增加表大小和列的幕后优化?

作为旁注,如果有任何更实用、经过验证的方法来存储此类数据,我对完全重组此表绝对没有任何限制。

CREATE TABLE `bitstrings` (
  `x` int(11) NOT NULL COMMENT 'roughly +/- 10^6 range',
  `z` int(11) NOT NULL COMMENT 'roughly +/- 10^6 range',
  `type` smallint(6) NOT NULL COMMENT 'range: 1-4096',
  `offset` smallint(6) NOT NULL COMMENT 'range: 1-65535',
  `bitstring` blob NOT NULL COMMENT 'binary data len: 1-8192'
) ENGINE=MyISAM DEFAULT CHARSET=utf-8;

--
-- Dumping data for table `bitstrings`
--

INSERT INTO `bitstrings` (`x`, `z`, `type`, `offset`, `bitstring`) VALUES
(0, 0, 1, 0, 0x52),
(0, 0, 2, 1878, 0x52);
Run Code Online (Sandbox Code Playgroud)

Rol*_*DBA 5

两件事情

  • 由于 x 和 z 的范围是 +/- 1000000,请使用meduimint(Meduimint 的范围是 +/- 8388608)
  • 由于偏移量和类型的范围是 1-65535,因此使用 smallint unsigned

做出这些改变

CREATE TABLE `bitstrings` ( 
  `x` meduimint(11) NOT NULL COMMENT 'roughly +/- 10^6 range', 
  `z` meduimint(11) NOT NULL COMMENT 'roughly +/- 10^6 range', 
  `type` smallint(6) UNSIGNED NOT NULL COMMENT 'range: 1-4096', 
  `offset` smallint(6) UNSIGNED NOT NULL COMMENT 'range: 1-65535', 
  `bitstring` blob NOT NULL COMMENT 'binary data len: 1-8192'
) ENGINE=MyISAM DEFAULT CHARSET=utf-8; 
Run Code Online (Sandbox Code Playgroud)

说到索引,你可能有一个选择

选择 #1:使用 ID 的主键

像这样设置表格

CREATE TABLE `bitstrings` ( 
  `id` int unsigned not null auto_incrmenet,
  `x` meduimint(11) NOT NULL COMMENT 'roughly +/- 10^6 range', 
  `z` meduimint(11) NOT NULL COMMENT 'roughly +/- 10^6 range', 
  `type` smallint(6) UNSIGNED NOT NULL COMMENT 'range: 1-4096', 
  `offset` smallint(6) UNSIGNED NOT NULL COMMENT 'range: 1-65535', 
  `bitstring` blob NOT NULL COMMENT 'binary data len: 1-8192',
  primary key (id),
  key xztype (x,z,type)
) ENGINE=MyISAM DEFAULT CHARSET=utf-8; 
Run Code Online (Sandbox Code Playgroud)

这可以让您使用 x 和 z 进行查询,同时检索所有 id 以快速参考该行:

SELECT id FROM bitstrings WHERE x=0 and z=0;
Run Code Online (Sandbox Code Playgroud)

如果您必须检索给定 id 的数据,您可以选择它作为

SELECT * FROM bitstrings WHERE id = 12;
Run Code Online (Sandbox Code Playgroud)

这将检索任何 x、z 和类型的特定信息。

选择 #2:使用 x,z,type 作为主键

运行此查询

SELECT COUNT(1) rcount,x,z,type FROM bitstrings GROUP BY x,z,type HAVING COUNT(1) > 1;
Run Code Online (Sandbox Code Playgroud)

如果此查询根本没有任何行返回,则这可能是您的主键

CREATE TABLE `bitstrings` ( 
  `x` meduimint(11) NOT NULL COMMENT 'roughly +/- 10^6 range', 
  `z` meduimint(11) NOT NULL COMMENT 'roughly +/- 10^6 range', 
  `type` smallint(6) UNSIGNED NOT NULL COMMENT 'range: 1-4096', 
  `offset` smallint(6) UNSIGNED NOT NULL COMMENT 'range: 1-65535', 
  `bitstring` blob NOT NULL COMMENT 'binary data len: 1-8192',
  primary key (x,z,type)
) ENGINE=MyISAM DEFAULT CHARSET=utf-8; 
Run Code Online (Sandbox Code Playgroud)

结论

由于所有查询都主要基于 x 和 z,因此任何一种选择都可以

  • 第一种选择会产生更大的 .MYI 文件,但有两种收集数据的方法(按 x、z 分组或按 id 粒度分组)。
  • 第二个选择只收集 x 和 z 但较小的 .MYI 文件。