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

use*_*026 55 mysql indexing

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

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

pax*_*blo 49

不,不是一般意义上的,我不相信即使5.6也有此功能.它能够只使用导致一列的一部分(该功能已经存在了很长一段时间),但在第二次或随后的字符,或任何其他更复杂的函数不1开始.

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

create index name_first_five on cust_table (name(5));
Run Code Online (Sandbox Code Playgroud)

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

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

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


axx*_*xis 31

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)
)
Run Code Online (Sandbox Code Playgroud)

正如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);
Run Code Online (Sandbox Code Playgroud)


Gab*_*esy 15

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

  • 更新:MySQL 8.0已发布,但仍然没有本地SQL表达式或函数索引可用。因此,您仍然需要使用生成的列索引作为解决方法。 (3认同)

小智 5

是的,我们可以在MySQL中创建功能索引。此功能从 MySQL 8.0.13 起可用。(其他 RDBMS 在其早期版本中具有此功能,但 MySQL 在其版本 8.0.13 中引入了它)。功能指标

这里我给出了在MySQL8.0中创建功能索引的例子

这是查询

SELECT * FROM app_user WHERE month(createdOn) = 5;

mysql> SELECT * FROM app_user WHERE month(createdOn) = 5;
7e9e2b7bc2e9bde15504f6c5658458ab - 74322 rows in set (5.01 sec)
Run Code Online (Sandbox Code Playgroud)

即使我在createdOn列上有索引,它也会执行超过5秒来获取74322条记录。(优化器不使用createdOn列上的索引,因为它被month()函数屏蔽了)

现在我已经使用以下语法在该列上创建了一个功能索引。

mysql> ALTER TABLE app_user ADD INDEX
         idx_month_createdon((month(createdOn)));
Query OK, 0 rows affected (1 min 17.37 sec) Records: 0 Duplicates: 0
Warnings: 0

mysql> SELECT * FROM app_user WHERE month(createdOn) = 5;
7e9e2b7bc2e9bde15504f6c5658458ab - 74322 rows in set (0.29 sec)
Run Code Online (Sandbox Code Playgroud)

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

Mysql网站上很难找到功能索引文档,都是以功能关键部分的名义

并且我们不能删除具有功能索引的列。为了实现这一点,我们首先需要删除功能索引。

mysql> ALTER TABLE app_user DROP COLUMN createdOn;
Cannot drop column 'createdOn' because it is used by a functional
index. In order to drop the column, you must remove the functional
index.
Run Code Online (Sandbox Code Playgroud)

如果您使用 MySQL > 5.7.5,则可以使用生成的列实现相同的目的。