Sql Postgres左侧外部联接似乎未使用表索引

Sql Postgres左侧外部联接似乎未使用表索引,sql,postgresql,indexing,query-optimization,outer-join,Sql,Postgresql,Indexing,Query Optimization,Outer Join,让我知道这是否应该发布在DBA.stackexchange.com上 我有以下疑问: SELECT DISTINCT "court_cases".* FROM "court_cases" LEFT OUTER JOIN service_of_processes ON service_of_processes.court_case_id = court_cases.id LEFT OUTER JOIN jobs ON jobs.service_of_process_id = service

让我知道这是否应该发布在DBA.stackexchange.com上

我有以下疑问:

SELECT DISTINCT "court_cases".*
FROM "court_cases"
LEFT OUTER JOIN service_of_processes
  ON service_of_processes.court_case_id = court_cases.id
LEFT OUTER JOIN jobs
  ON jobs.service_of_process_id = service_of_processes.id
WHERE
  (jobs.account_id = 250093
  OR court_cases.account_id = 250093)
ORDER BY
  court_cases.court_date DESC NULLS LAST,
  court_cases.id DESC
LIMIT 30
OFFSET 0;
但运行需要2-4秒,在web应用程序中,这对于单个查询是不可接受的

我按照建议对查询运行了
EXPLAIN(ANALYZE,BUFFERS)
,并将结果放在这里:

查询中涉及的表的表定义如下(包括外键关系的索引):

是否因为
WHERE
子句正在从两个不同的表查询,所以使用索引时出现问题?我可以对查询进行什么样的索引或更改以加快运行速度

以下是相关表格的当前大小:

PSQL=# select count(*) from service_of_processes;
 count  
--------
 103787
(1 row)

PSQL=# select count(*) from jobs;
 count  
--------
 108995
(1 row)

PSQL=# select count(*) from court_cases;
 count 
-------
 84410
(1 row)

编辑:如果有必要的话,我正在使用Postgresql 9.3.1。

我将尝试修改查询,如下所示:

SELECT DISTINCT "court_cases".*
FROM "court_cases"
LEFT OUTER JOIN service_of_processes
  ON service_of_processes.court_case_id = court_cases.id
LEFT OUTER JOIN jobs
  ON jobs.service_of_process_id = service_of_processes.id and jobs.account_id = 250093
WHERE
  (court_cases.account_id = 250093)
ORDER BY
  court_cases.court_date DESC NULLS LAST,
  court_cases.id DESC
LIMIT 30
OFFSET 0;

我认为问题在于,查询计划优化器没有正确分解where过滤器,一个非常奇怪的性能缺陷或子句会使优化查询变得困难。一个想法是将查询的两个部分分成两个独立的子查询。这实际上大大简化了其中一项(关于
法庭案件.account\u id

请尝试以下版本:

(SELECT cc.*
 FROM "court_cases" cc
 WHERE cc.account_id = 250093
 ORDER BY cc.court_date DESC NULLS LAST,
          cc.id DESC
 LIMIT 30
) UNION ALL
(SELECT cc.*
 FROM "court_cases" cc LEFT OUTER JOIN
      service_of_processes sop
      ON sop.court_case_id = cc.id LEFT OUTER JOIN
      jobs j
      ON j.service_of_process_id = sop.id
 WHERE (j.account_id = 250093 AND cc.account_id <> 250093)
 ORDER BY cc.court_date DESC NULLS LAST, id DESC
 LIMIT 30
)
ORDER BY court_date DESC NULLS LAST,
         id DESC
LIMIT 30 OFFSET 0;

请注意,第二个查询使用
和cc.count\u id 250093
,这可以防止重复记录。这消除了对
不同的
联合
(无
联合所有
)的需要。

这不起作用:\n它不包括那些
乔布斯.account\u id=250093
法院案例.account\u id!=250093,这就是原始查询中存在
的原因:(你说得对……事实上,问题是where条件只能在计算完整的联接集之后才能计算,因为表很大,这可能需要很长时间。这不是索引问题……我将尝试将查询分解为两个子查询,拆分where筛选器,然后应用与union o不同的select对于上一个创建索引的两个查询语法错误,您缺少索引的名称,
上的
。应该类似于
create index jobs\u account\u id\u sop\u id on jobs(account\u id,service\u of\u process\u id);
create index court_cases_accountid_courtdate_id on court_cases(account_id, court_date, id);
create index jobs_accountid_sop on jobs(account_id, service_of_process_id);