MySQL's documentation说:

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

然而,我想知道使用此功能是否会带来任何性能损失.假设我有一个大表,存储用户看到 comments 的时间:

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_iduser_id)上指定复合键,并在user_id上指定非复合键,我就可以使用最左边的前置规则进行comment_id搜索.然而,如果只有comment_id上有显式键,那么只指定comment_id(即SELECT * FROM comment_views WHERE comment_id = 123)的查找会更快吗?

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

我try 在有和没有额外索引的情况下运行EXPLAIN,除了显示我的新索引的possible_keys之外,解释没有任何变化.事实上,EXPLAIN preferred似乎是复合密钥.也许是因为它在表定义中是第一个,或者它只是更喜欢唯一的键(尽管最左边的前置符并不唯一).我不知道我无法找到更多有关SQL实际上如何使用引擎盖下最左边的前置符的信息.

推荐答案

差异是如此之小,以至于可以预见.

争论点:

  • col 1 INT,col 2 INT --一旦索引页面被缓存,它们就可以随时用于需要SEN(col 1)或SEN(col 1 col 2)的查询. 这有时会是一个优势.
  • co 11 INT,col 2 VAR(255)--现在综合指数是批量的. 因此,当您只需要col 1时,它可能会更慢.
  • col1 TinYint,col2. --如果col 1的基数较低(例如,真/假),INDEX(col1)可能永远不会被使用.
  • SEN(col1)、SEN(col1,col2)显然占用更多磁盘空间.

其他注释:

  • 很少需要BIGINT个. 例如,你真的有20亿用户吗?
  • id真的需要吗? 或者PRIMARY KEY(user_id, comment_id)就够了吗? (或者相反的顺序.) 这可能有帮助,原因有几个.
  • 声明FOREIGN KEY将创建INDEX if needed. 因此,创建声明FK的复合索引before.
  • We need to see the queries to make further suggestions.

Mysql相关问答推荐

SQL中的搜索模式

如何获得表中只有最大值行的一个列被另一个列分区?

根据计数按月和年对数据进行分组()

在停靠容器中备份和恢复MySQL数据库时出现Unicode字符问题

如何从MySQL数据库中提取入职第一个月的工作天数?

MySQL工作台的编码问题

在MySQL中查找包含无效正则表达式的行

在带有 D.I 的 .NET AWS Lambda 中使用 MySql.Data

根据 Power Query 中的条件替换值

如何优化使用多个 LEFT JOIN 和 GROUP BY 子句的慢速 MySQL 查询?

获取 MySQL 中每一行之间负差的总和

MySQL 使用了错误的索引

如何从将分钟、天、月和年存储在不同列中的表中查询数据

MySQL按连续值和计数分组

为什么 ORDER BY 'id' 'desc' 不返回语法错误?

最好的 MySQL 性能调优工具?

从一个带有连接的表中删除

MySQL计算特定值的列

MySQL获取两个值之间的随机值

MySQL 更新连接表