提问者:小点点

有没有可能在MySQL中有基于函数的索引?


我记得在Oracle中,可以基于函数进行索引,例如substring(id,1,8)

MySQL支持这个吗? 如果没有,是否有其他选择?


共3个答案

匿名用户

不,不是一般意义上的,我不相信即使是5.6(这个答案刚开始写的时候的最新版本)也有这个功能。 值得注意的是,8.0.13和更高版本现在支持函数索引,允许您在不需要下面描述的触发器方法的情况下实现所需的内容。

请参阅https://dev.mysql.com/doc/refman/8.0/en/create-index.html以获得更多详细信息。

如果您运行的是较旧版本的MySQL,则可以只使用列的前导部分(此功能已存在很长时间),而不能使用从第二个或后续字符开始的部分,也不能使用任何其他更复杂的函数。

例如,下面使用名称的前五个字符创建索引:

create index name_first_five on cust_table (name(5));

对于更复杂的表达式,可以通过另一列中包含可索引数据,然后使用INSERT/UPDATE触发器确保正确填充该列来实现类似的效果。

除了为冗余数据浪费空间之外,这几乎是一回事。

而且,尽管它在技术上违反了3NF,但通过使用触发器来保持数据同步(这是为了增加性能而经常做的事情),这一点得到了缓解。

匿名用户

MySQL从8.0.13开始支持此功能

https://dev.mysql.com/doc/refman/8.0/en/create-index.html#create-index-functional-key-parts

MySQL8.0.13和更高版本支持索引表达式值而不是列或列前缀值的功能关键部分。 使用功能性关键部件可以对不直接存储在表中的值进行索引。 示例:

CREATE TABLE t1 (col1 INT, col2 INT, INDEX func_index ((ABS(col1))));
CREATE INDEX idx1 ON t1 ((col1 + col2));
CREATE INDEX idx2 ON t1 ((col1 + col2), (col1 - col2), col1);
ALTER TABLE t1 ADD INDEX ((col1 * 40) DESC);

一个具有多个关键部分的索引可以混合非功能性和功能性关键部分。

对于8.0.13之前的版本,有以下备选方案:

1.自MySQL 5.7.6以来

您可以使用自动生成的列来保存子字符串,其中包含索引:

CREATE TABLE SomeTable (
    id CHAR(10),
    sub_id CHAR(8) AS SUBSTRING(id, 1, 8) STORED, INDEX(sub_id)
)

正如Benjamin所指出的,InnoDB支持虚拟列的辅助索引,因此可以省略STORED关键字。 实际上,虚拟列上的辅助索引可能更可取。 此处提供更多信息:辅助索引和生成的列

2.MySQL 5.7.6之前的版本

可以使用触发器更新的列,列上有索引:

CREATE TABLE SomeTable (
    id CHAR(10),
    sub_id CHAR(8) , INDEX(sub_id)
);

CREATE TRIGGER TR_SomeTable_INSERT_sub_id
    BEFORE INSERT
    ON SomeTable FOR EACH ROW 
    SET NEW.sub_id = SUBSTRING(NEW.id, 1, 8);

CREATE TRIGGER TR_SomeTable_UPDATE_sub_id
    BEFORE UPDATE
    ON SomeTable FOR EACH ROW 
    SET NEW.sub_id = SUBSTRING(NEW.id, 1, 8);

匿名用户

从MySQL5.7.5开始,使用新生成的列,这是可能的。