我有以下表格:
-
work_units
- 不言自明
-
workers
- 不言自明
-
skills
- 如果你想从事每个工作单位,都需要一些技能。每个工人都精通多项技能。
-
work_units_skills
- 连接表
-
workers_skills
- 连接表
工作人员可以请求将下一个适当的免费最高优先级(无论这意味着什么)工作单元分配给她。
目前我有:
SELECT work_units.*
FROM work_units
-- some joins
WHERE NOT EXISTS (
SELECT skill_id
FROM work_units_skills
WHERE work_unit_id = work_units.id
EXCEPT
SELECT skill_id
FROM workers_skills
WHERE worker_id = 1 -- the worker id that made the request
)
-- AND a bunch of other conditions
-- ORDER BY something complex
LIMIT 1
FOR UPDATE SKIP LOCKED;
不过,这种情况会使查询速度慢 8-10 倍。
有没有更好的方式来表达work_units
的技能应该是workers
的技能或者什么来改进当前的查询?
更多背景信息:
- The
skills
桌子相当小。
- Both
work_units
and workers
往往具有很少的相关技能。
-
work_units_skills
有索引work_unit_id
.
- 我尝试将查询移至
workers_skills
进入 CTE。这略有改善(10-15%),但仍然太慢。
- 没有技能的工作单位可以由任何用户接手。又名空集是每个集合的子集。
一种简单的加速方法是使用EXCEPT ALL https://www.postgresql.org/docs/9.4/static/queries-union.html代替EXCEPT
。后者会删除重复项,这在这里是不必要的,而且可能会很慢。
另一种可能会更快的替代方法是使用进一步的NOT EXISTS
而不是EXCEPT
:
...
WHERE NOT EXISTS (
SELECT skill_id
FROM work_units_skills wus
WHERE work_unit_id = work_units.id
AND NOT EXISTS (
SELECT skill_id
FROM workers_skills ws
WHERE worker_id = 1 -- the worker id that made the request
AND ws.skill_id = wus.skill_id
)
)
Demo
http://rextester.com/AGEIS52439 http://rextester.com/AGEIS52439 - 与LIMIT
删除以进行测试
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)