11

我有一个非常大的表(数百万条记录),其中包含大约 8 个字段作为主键。为简单起见,可以说该表如下所示:

    key_1 | key_2 | key_3 | ... | key_8 | value

给定 key_1 的值,我需要获取 key_2、key_3、...、key_8 的所有可能值,如下所示:

    SELECT DISTINCT key_2 FROM table1 WHERE key_1 = 123;
    SELECT DISTINCT key_3 FROM table1 WHERE key_1 = 123;
    ...
    SELECT DISTINCT key_8 FROM table1 WHERE key_1 = 123;

我的问题是这个查询比我的性能需要慢得多,而且这个表中的数据相当稳定,很少更新(每隔几天一次)。table_1 也可能是一个缓慢的子查询。除了在数据库中创建一个额外的表并在每次更新数据库时手动更新它,还有另一种解决方案可以给我快速的结果。我需要它跨多个 MySQL 会话工作。

4

2 回答 2

19

无法用我们掌握的信息给出明确的答案,但让我们从这些开始:

您在 key_1 上有索引吗?

没有它,每个查询本身就已经很慢,只需要查找 123。

您在 (key_1, key_2) 上有索引吗?

因为select distinct key_2 where key_1 = 123如果它可以单独从索引中获取所有必要的数据,那真的很快。无需访问表。

行/索引是固定大小的吗?

遍历固定大小的表/行会更快,因为只需计算偏移量就可以知道第 x 条记录在哪里。可变行大小的表速度较慢。

您是否尝试过添加自动增量代理主键?

当索引只需要存储列和一个小的主键时,索引会更好地工作。复合主键速度较慢。

您是否考虑过只读表?

您可以打包 myisam 表以进行快速访问,但它们变为只读的。这是一个有其用途的黑客。

更进一步,您是否考虑过数据仓库?

如果表格不经常更改,最好复制信息以便快速访问。

可以发表show create table声明吗?查看列和索引会有所帮助。可以发表explain select声明吗?查看使用了哪些索引会有所帮助。

于 2012-05-29T13:52:52.787 回答
4
SELECT DISTINCT key_2 FROM table1 WHERE key_1 = 123;

这可以使用您的主键索引(key_1、key_2 等)。它将执行索引扫描,这比表扫描或临时表要快。

SELECT DISTINCT key_3 FROM table1 WHERE key_1 = 123;

无法使用主键,因为 key_1 和 key_3 的组合不构成主键的前缀。您需要按顺序在 key_1 和 key_3 上创建复合索引。然后,它也可以使用该索引来执行索引扫描。

SELECT DISTINCT key_8 FROM table1 WHERE key_1 = 123;

需要 key_1 和 key_8 上的索引,按此顺序。和上面一样。

于 2012-05-29T14:21:44.923 回答