You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

MySQL是否支持Partial Indexes?如何创建带WHERE条件的Partial Indexes?

在MySQL中实现Partial Indexes(部分索引)

好问题!你提到的这种只包含表中部分行的索引,MySQL里其实也支持,它的官方叫法是带条件的索引(Conditional Indexes),实现思路和你在SQL Server里用的方式很像,但有几个细节需要留意。

基本语法

和SQL Server的写法几乎一致,你可以直接在CREATE INDEX语句里添加WHERE子句来指定要纳入索引的行。针对你给出的业务场景,对应的MySQL语句是:

CREATE INDEX ix1_case ON client_case (date) 
WHERE status = 'pending';

这个索引只会存储status = 'pending'的行,完全符合你说的“低成本”需求——如果表有500万行,但pending状态的只有1000行,那这个索引的体积就只有全表索引的1/5000,无论是存储空间还是查询效率都会大幅提升。

关键限制

虽然语法相似,但MySQL对这种索引有一些硬性要求,你需要注意:

  • 存储引擎限制:只有InnoDB和MyISAM存储引擎支持带条件的索引,MEMORY等其他引擎不兼容。
  • 版本要求:从MySQL 5.7版本开始才引入这个特性,如果你用的是5.6及更早的版本,就没法直接用这种方式了。
  • 条件列类型限制WHERE子句里用到的列不能是TEXT、BLOB或者JSON这类大对象类型,只能是数值、普通字符串(VARCHAR/CHAR等)、日期这类基础数据类型。
  • 允许的操作符:条件里只能用=<>><>=<=BETWEENIN以及IS NULL/IS NOT NULL,不能用LIKE或者自定义函数这类复杂条件。

进阶用法

你还可以给索引添加多个列,同时组合多个过滤条件,比如需要同时筛选状态为pending且未归档的行:

CREATE INDEX ix_pending_unarchived_date ON client_case (date, client_id)
WHERE status = 'pending' AND is_archived = 0;

这个索引会只包含符合双重条件的行,同时对dateclient_id列建立索引,适合那些需要同时过滤这两个条件的查询场景。

查询时的索引匹配逻辑

当你的查询语句的WHERE条件完全匹配索引的过滤条件时,MySQL优化器会自动选择这个部分索引。比如下面的查询就会用到我们创建的ix1_case索引:

SELECT * FROM client_case 
WHERE status = 'pending' AND date >= '2024-01-01';

但如果查询的条件不包含status='pending'(比如查status='closed'的行),这个索引就不会被使用,这和其他数据库的部分索引行为一致。

内容的提问来源于stack exchange,提问作者The Impaler

火山引擎 最新活动