外键如何根据数据库的性能(索引)解决查询?

How does foreign key resolve queries in terms of performance(indexing) on databases?

我想知道当我有或没有外键时,使用连接操作的查询如何执行。例如,给定以下架构:

CREATE TABLE EMPLOYEE 
(
    ID BIGINT NOT NULL,
    NAME VARCHAR(240),
    DEPTID BIGINT
);

ALTER TABLE EMPLOYEE 
    ADD CONSTRAINT P_EMPLOYEE PRIMARY KEY (ID);

CREATE TABLE DEPARTMENT 
(
    ID BIGINT NOT NULL,
    NAME VARCHAR(240)
);

ALTER TABLE DEPARTMENT 
    ADD CONSTRAINT P_DEPARTMENT PRIMARY KEY (ID);

INSERT INTO DEPARTMENT (ID, NAME) 
VALUES (1, 'A'), (2, 'B'), (3, 'C');

INSERT INTO EMPLOYEE (ID, NAME, DEPTID) 
VALUES (1, 'Bob', 1), (2, 'John', 1),
       (3, 'Mike', 2), (4, 'Josh', 2),
       (5, 'Lisa', 3), (6, 'Claire', 3);

ALTER TABLE EMPLOYEE 
    ADD CONSTRAINT F_EMP_DEP 
        FOREIGN KEY (DEPTID) REFERENCES DEPARTMENT (ID)
            ON DELETE NO ACTION
            ON UPDATE NO ACTION
            ENFORCED
            ENABLE QUERY OPTIMIZATION;

CREATE INDEX I_EMP_DEPTID ON EMPLOYEE (DEPTID);

鉴于我有以下查询:

SELECT * 
FROM EMPLOYEE E
JOIN DEPARTMENT D ON E.DEPTID = D.ID
WHERE D.NAME = 'A';

当我询问它的执行计划时,它给了我下面的结果。这意味着查询正在使用索引 I_EMP_DEPTID 来改进连接操作。

但是,如果我删除索引 I_EMP_DEPTID

DROP INDEX I_EMP_DEPTID;

并再次询问执行计划,这次是 运行 一次 table 扫描。见下图。

如果您阅读了 IBM 关于此主题的 FK docs,它说:

Referential integrity is imposed by adding foreign key (or referential) constraints to table and column definitions, and to create an index on all the foreign key columns. Once the index and foreign key constraints are defined, changes to the data within the tables and columns is checked against the defined constraint. Completion of the requested action depends on the result of the constraint checking.

所以这意味着在这种情况下我必须将 FK 和 INDEX 创建为单独的任务,这总是正确的吗?这个概念是否适用于所有 SQL 数据库(例如:Oracle、Postgres、MySQL、SQL 服务器)?我的意思是这是 FK 不会自动索引子列或期望它们被索引的一般概念吗?

关于其他数据库不能说太多,但关于 MySQL 似乎索引是在引用 table 上自动创建的,如文档所述:

MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. Such an index is created on the referencing table automatically if it does not exist. This index might be silently dropped later if you create another index that can be used to enforce the foreign key constraint. index_name, if given, is used as described previously. Reference link

先理清概念很重要。 “外键”是列,而“外键约束”是完整性规则。

现在,当存在有助于快速查找相关行的索引时,检查完整性规则引擎的效率会更高。通常,基于堆的引擎,如 Oracle、DB2、PostgreSQL 不会在您创建外键约束时自动添加索引。基于聚集索引的引擎,如 MariaDB、MySQL 和 SQL 服务器默认执行此操作。

这两个模型完全不同,一般来说,基于堆的引擎往往更高效。然而,在这些引擎中,数据库设计者需要手动设置有用的 FK 索引。如果设计者忘记这样做(经常发生),那么数据修改语句和连接的性能会随着时间的推移而恶化。另一方面,有经验的设计人员可以添加高度自定义的索引(包括覆盖索引、特定列排序、表达式等),以最少数量的索引为许多解决方案提供服务。这需要更多知识,根据我的经验,大多数设计师可能不会充分利用这些功能。