是否可以在MySQL中使用基于函数的索引?

时间:2012-05-15 06:10:16

标签: mysql indexing

我记得在Oracle中,可以根据函数进行索引,例如: SUBSTRING(id,1,8)

MySQL是否支持此功能?如果没有,是否有其他选择?

4 个答案:

答案 0 :(得分:49)

不,不是一般意义上的,我不相信即使是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));

对于更复杂的表达式,您可以通过使用另一个列并在其中包含可索引数据来实现类似的效果,然后使用插入/更新触发器来确保它已正确填充。

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

而且,虽然它在技术上违反了3NF,但通过使用触发器来保持数据同步可以缓解这种情况(这通常是为了提高性能)。

答案 1 :(得分:28)

MySQL不支持此功能,但还有其他选择。

<强> 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关键字。实际上,虚拟列上的二级索引可能更可取。更多信息:Secondary Indexes and Generated Columns

<强> 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);

答案 2 :(得分:15)

从MySQL 5.7.5开始,可以使用新的Generated Columns

答案 3 :(得分:0)

是的,我们可以在MySQL中创建功能索引。 MySQL 8.0.13提供了此功能。 (其他RDBMS在其较早的版本中具有此功能,但MySQL在其8.0.13版本中引入了此功能)。 Functional Index

这里我举了一个在MySQL8.0中创建功能索引的示例

这是查询

  

从app_user中选择*,其中month(createdOn)= 5;

     

mysql>从app_user中选择*,其中month(createdOn)= 5;   7e9e2b7bc2e9bde15504f6c5658458ab-集合中的74322行(5.01秒)

即使我在createdOn列上有索引,它也会执行5秒钟以上的时间来获取74322条记录。(optimizer不使用createdOn列上的索引,因为它被month()函数掩盖了)

现在,我使用以下语法在列上创建了功能索引。

  

mysql>更改表app_user添加索引   idx_month_createdon((month(createdOn)));   查询正常,受影响的0行(1分钟17.37秒)记录:0重复项:0   警告:0

     

mysql>从app_user中选择*,其中month(createdOn)= 5;   7e9e2b7bc2e9bde15504f6c5658458ab-集合中的74322行(0.29秒)

创建功能索引后,它将在0.29秒内执行。

在Mysql网站上很难找到功能索引文件,它的名称为functional key parts

并且我们不能删除具有功能索引的列。为此,我们首先需要删除功能索引。

  

mysql> alter table app_user删除列createdOn;   无法删除列“ createdOn”,因为该列已由函数使用   指数。为了删除列,必须删除功能   索引。

如果您使用的是MySQL> 5.7.5,则可以使用generated columns来实现相同的目的。