【发布时间】:2018-05-06 13:19:28
【问题描述】:
我有以下表格:
-
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 的技能的子集或改进当前查询的东西?
更多上下文:
-
skills表相当小。 -
work_units和workers的相关技能往往很少。 -
work_units_skills在work_unit_id上有索引。 - 我尝试将
workers_skills上的查询移至CTE。这带来了轻微的改善 (10-15%),但仍然太慢了。 - 任何用户都可以拾取没有技能的工作单元。也就是空集是每个集的子集。
【问题讨论】:
-
我认为魔鬼可能在 cmets 中缺失的细节中(如
ORDER BY something complex bunch of conditions等)。所以,如果您可以发布EXPLAIN,它可能会有所帮助 -
@KaushikNayak,我尝试删除个别条件并使用更简单的东西进行订购。查询仍然慢得多。所以它不是这个和其他一些条件的组合。可能是这个和其他两个+条件,但不太可能。不幸的是,我无法发布
EXPLAIN,因为该项目是私人项目,但如果您有任何预感,我可以回答您的问题。 -
请Edit您的问题并添加使用
explain (analyze, verbose, buffers)生成的执行计划。 Formatted text 请no screen shots。如果您不想(或不能)共享表名,请将其上传到explain.depesz.com 并启用混淆计划的选项(尽管执行计划很少会泄露任何机密信息) -
2 个问题? 1. 我可以对您的数据库设计进行一些更改吗?例如添加 1 或 2 个额外字段。 2. 您使用哪种 DBMS?
-
@g.Irani,对于前者 - 你可以。事实上,我正在考虑两个这样的解决方案,其中包含一个额外的列 - 一个涉及位掩码,另一个涉及哈希。两者都快得多(在转储基准上提高了约 60%),但似乎仍然不够快。对于后者 - 根据标签 - postgres.
标签: sql postgresql performance relational-division set-operations