MySQL table 上的指数选择
Choice of indices on a MySQL table
我有以下 MySQL table:
CREATE TABLE example (
id INT AUTO_INCREMENT NOT NULL,
node0 SMALLINT DEFAULT 0 NOT NULL,
node1 SMALLINT DEFAULT 0 NOT NULL,
node2 SMALLINT DEFAULT 0 NOT NULL,
node3 SMALLINT DEFAULT 0 NOT NULL,
version SMALLINT DEFAULT 1 NOT NULL,
user_id INT DEFAULT NULL,
score INT DEFAULT 0 NOT NULL,
datetime BIGINT NOT NULL,
INDEX IDX_22B017FAA76ED395 (user_id), PRIMARY KEY(id)
)
ALTER TABLE example ADD CONSTRAINT FK_22B017FAA76ED395 FOREIGN KEY (user_id) REFERENCES user (id);
table 将相当大(-ish)(几百万个条目),我想知道为性能索引列的最佳方式是什么。
主要查询table,获取所有匹配的行:
- 一个 node0 值
- 节点 1 值
- 一个 node2 值
- 一个 node3 值
- 版本值
...使用 Join 语句获取关联用户(user_id 字段)
这些字段(node0, node1, node2, node3, version) 可以形成一个键(所有这些字段的两行不能具有相同的值),但我想将ID保留为自动递增钥匙,这样我就可以订购它们了。
我应该为这些字段添加辅助键吗?或者将它们作为主键并将 ID 作为辅助键? And/or 添加单个索引?
您可能希望 multicolumn indexes 匹配您最常见的查询模式。我猜你说你的查询模式是这样的。
WHERE node0 = #constant#
AND node1 = #constant#
AND node2 = #constant#
AND node3 = #constant#
AND version = #constant#
这个多列索引会有所帮助。
INDEX example_nodes_version (node0, node1, node2, node3, version)
如果您不按顺序过滤这些条件,它将无用。例如,它会帮助这个
WHERE node0 = #constant#
AND node1 = #constant#
但不是这个
WHERE node2 = #constant#
AND version = #constant#
如果您的绝大多数查询都遵循第一个查询模式,这里有一种处理索引的更快方法。
您可以使主键成为这些列的串联,并创建一个 UNIQUE 键来处理您的自动递增 ID。
CREATE TABLE example (
id INT AUTO_INCREMENT NOT NULL,
node0 SMALLINT DEFAULT 0 NOT NULL,
node1 SMALLINT DEFAULT 0 NOT NULL,
node2 SMALLINT DEFAULT 0 NOT NULL,
node3 SMALLINT DEFAULT 0 NOT NULL,
version SMALLINT DEFAULT 1 NOT NULL,
user_id INT DEFAULT NULL,
score INT DEFAULT 0 NOT NULL,
datetime BIGINT NOT NULL,
INDEX IDX_22B017FAA76ED395 (user_id),
PRIMARY KEY(node0, node1, node2, node3, version),
UNIQUE INDEX ex_autoincrement (id)
)
为什么这有帮助? InnoDB 使用 clustered index storage scheme。也就是说,它将所有数据存储为其主键的一部分。因此,根据上面的过滤进行查找将直接访问您的数据,而不必搜索索引,然后搜索单独的 table.
除非您预计这个 table 很大(一百万行或更多)并且被大量查询,否则您应该保持简单:创建索引以匹配您的查询模式并使用 id
作为主键。
并且知道这一点:随着应用程序及其 table 的增长,通常需要新的索引来匹配真实世界的查询模式。根据经验添加新索引很容易。
我有以下 MySQL table:
CREATE TABLE example (
id INT AUTO_INCREMENT NOT NULL,
node0 SMALLINT DEFAULT 0 NOT NULL,
node1 SMALLINT DEFAULT 0 NOT NULL,
node2 SMALLINT DEFAULT 0 NOT NULL,
node3 SMALLINT DEFAULT 0 NOT NULL,
version SMALLINT DEFAULT 1 NOT NULL,
user_id INT DEFAULT NULL,
score INT DEFAULT 0 NOT NULL,
datetime BIGINT NOT NULL,
INDEX IDX_22B017FAA76ED395 (user_id), PRIMARY KEY(id)
)
ALTER TABLE example ADD CONSTRAINT FK_22B017FAA76ED395 FOREIGN KEY (user_id) REFERENCES user (id);
table 将相当大(-ish)(几百万个条目),我想知道为性能索引列的最佳方式是什么。
主要查询table,获取所有匹配的行:
- 一个 node0 值
- 节点 1 值
- 一个 node2 值
- 一个 node3 值
- 版本值
...使用 Join 语句获取关联用户(user_id 字段)
这些字段(node0, node1, node2, node3, version) 可以形成一个键(所有这些字段的两行不能具有相同的值),但我想将ID保留为自动递增钥匙,这样我就可以订购它们了。
我应该为这些字段添加辅助键吗?或者将它们作为主键并将 ID 作为辅助键? And/or 添加单个索引?
您可能希望 multicolumn indexes 匹配您最常见的查询模式。我猜你说你的查询模式是这样的。
WHERE node0 = #constant#
AND node1 = #constant#
AND node2 = #constant#
AND node3 = #constant#
AND version = #constant#
这个多列索引会有所帮助。
INDEX example_nodes_version (node0, node1, node2, node3, version)
如果您不按顺序过滤这些条件,它将无用。例如,它会帮助这个
WHERE node0 = #constant#
AND node1 = #constant#
但不是这个
WHERE node2 = #constant#
AND version = #constant#
如果您的绝大多数查询都遵循第一个查询模式,这里有一种处理索引的更快方法。
您可以使主键成为这些列的串联,并创建一个 UNIQUE 键来处理您的自动递增 ID。
CREATE TABLE example (
id INT AUTO_INCREMENT NOT NULL,
node0 SMALLINT DEFAULT 0 NOT NULL,
node1 SMALLINT DEFAULT 0 NOT NULL,
node2 SMALLINT DEFAULT 0 NOT NULL,
node3 SMALLINT DEFAULT 0 NOT NULL,
version SMALLINT DEFAULT 1 NOT NULL,
user_id INT DEFAULT NULL,
score INT DEFAULT 0 NOT NULL,
datetime BIGINT NOT NULL,
INDEX IDX_22B017FAA76ED395 (user_id),
PRIMARY KEY(node0, node1, node2, node3, version),
UNIQUE INDEX ex_autoincrement (id)
)
为什么这有帮助? InnoDB 使用 clustered index storage scheme。也就是说,它将所有数据存储为其主键的一部分。因此,根据上面的过滤进行查找将直接访问您的数据,而不必搜索索引,然后搜索单独的 table.
除非您预计这个 table 很大(一百万行或更多)并且被大量查询,否则您应该保持简单:创建索引以匹配您的查询模式并使用 id
作为主键。
并且知道这一点:随着应用程序及其 table 的增长,通常需要新的索引来匹配真实世界的查询模式。根据经验添加新索引很容易。