You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

双外键场景下未匹配员工查询及性能优化技术问询

针对Companies与Employees表的查询优化方案

针对你提出的两个查询需求,我整理了高效的SQL写法和性能优化建议,帮你解决之前性能不佳的问题:

需求1:获取所有在Companies表中列出的公司任职的员工

即员工的CompId或FilId至少有一个关联到Companies表中的记录。

高效SQL写法

推荐使用UNION替代OR(避免OR导致索引失效的问题):

SELECT e.*
FROM Employees e
JOIN Companies c ON c.Id = e.CompId
UNION
SELECT e.*
FROM Employees e
JOIN Companies c ON c.Id = e.FilId;

如果你的数据库优化器对OR的支持较好,也可以用更简洁的EXISTS写法:

SELECT e.*
FROM Employees e
WHERE EXISTS (SELECT 1 FROM Companies c WHERE c.Id = e.CompId)
   OR EXISTS (SELECT 1 FROM Companies c WHERE c.Id = e.FilId);

性能优化关键

  • 确保Companies.Id是主键(默认自带聚簇索引,查询效率最高)
  • 给Employees表的CompId和FilId分别创建独立的非聚簇索引:
    CREATE INDEX idx_employees_compid ON Employees(CompId);
    CREATE INDEX idx_employees_filid ON Employees(FilId);
    
    这两个索引能让数据库快速定位到关联Companies的员工记录,避免全表扫描。

需求2:获取所有未在Companies表中列出的公司任职的员工

即员工的CompId和FilId均未在Companies表中存在。

高效SQL写法

推荐使用NOT EXISTS(比NOT IN更安全,不会因Companies.Id存在NULL值导致结果异常):

SELECT e.*
FROM Employees e
WHERE NOT EXISTS (SELECT 1 FROM Companies c WHERE c.Id = e.CompId)
  AND NOT EXISTS (SELECT 1 FROM Companies c WHERE c.Id = e.FilId);

也可以用LEFT JOIN + IS NULL的写法,性能和NOT EXISTS相近:

SELECT e.*
FROM Employees e
LEFT JOIN Companies c1 ON c1.Id = e.CompId
LEFT JOIN Companies c2 ON c2.Id = e.FilId
WHERE c1.Id IS NULL AND c2.Id IS NULL;

性能优化关键

  • 复用需求1中创建的idx_employees_compid和idx_employees_filid索引,数据库能快速过滤掉已关联Companies的员工
  • 如果只需要查询员工的部分字段,可以创建覆盖索引,避免回表查询(比如只需要员工ID和姓名):
    CREATE INDEX idx_employees_compid_covering ON Employees(CompId) INCLUDE (Id, Name);
    CREATE INDEX idx_employees_filid_covering ON Employees(FilId) INCLUDE (Id, Name);
    

内容的提问来源于stack exchange,提问作者Denis Evseev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:18:33