在MySQL中,复合索引的最左边前缀是否与非复合索引一样性能?

问题描述 投票:0回答:1

MySQL 的文档 说:

如果表具有多列索引,则优化器可以使用索引的任何最左边的前缀来查找行。例如,如果您在 (col1, col2, col3) 上有一个三列索引,则您在 (col1)、(col1, col2) 和 (col1, col2, col3) 上具有索引搜索功能。

但是,我想知道使用此功能是否会带来任何性能损失。假设我有一个大表来存储用户何时看到评论:

CREATE TABLE `comment_views` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) NOT NULL,
  `comment_id` bigint(20) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `comment_views_comment_id_user_id_unique` (`comment_id`,`user_id`),
  KEY `comment_views_user_id_foreign` (`user_id`),
  CONSTRAINT `comment_views_comment_id_foreign` FOREIGN KEY (`comment_id`) REFERENCES `comments` (`id`),
  CONSTRAINT `comment_views_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=38821916 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

通过在 (

comment_id
,
user_id
) 上指定复合键,并在
user_id
上指定非复合键,我可以使用最左边的前缀规则通过
comment_id
进行搜索。但是,如果仅
comment_id
上有显式键,则仅指定
comment_id
(即
SELECT * FROM comment_views WHERE comment_id = 123
)的查找会更快吗?

如果组合键不唯一、列是字符串或者列可以为空,那么答案会改变吗?如果我改用范围、连接、依赖子查询、覆盖索引查询或其他索引访问,怎么样?

我尝试运行带或不带额外索引的 EXPLAIN,除了显示我的新索引的

possible_keys
之外,解释没有改变。事实上,它看起来像是 EXPLAIN preferred 组合键。也许是因为它位于表定义中的第一个,或者它只是更喜欢唯一的键(即使最左边的前缀不是唯一的)。我不知道。我无法找到有关 MySQL 如何实际使用最左边前缀的更多信息。

mysql indexing query-optimization composite-index
1个回答
0
投票

差异很小,可以忽略不计。

争论点:

  • col1 INT、col2 INT——一旦索引页被缓存,它们就可以随时用于需要 INDEX(col1) 或 INDEX(col1 col2) 的查询。这有时会是一个优势。
  • co11 INT, col2 VARCHAR(255) -- 现在复合索引是批量索引。所以当你只需要 col1 时,它可能会更慢。
  • col1 TINYINT, col2 ... -- 如果 col1 的基数较低(例如 true/false),则
    INDEX(col1)
    可能永远不会被使用。
  • INDEX(col1), INDEX(col1, col2) 显然需要更多的磁盘空间。

其他注意事项:

  • 很少需要
    BIGINT
    。例如,你真的有 20 亿用户吗?
  • id
    真的需要吗?或者
    PRIMARY KEY(user_id, comment_id)
    就足够了? (或相反的顺序。)这可能有几个原因。
  • 声明
    FOREIGN KEY
    将创建
    INDEX
    如果需要。因此,在声明 FK 之前创建复合索引。
  • 我们需要查看查询以提出进一步的建议。
© www.soinside.com 2019 - 2024. All rights reserved.