0

对 postgres 来说很新,似乎在这里有问题,我不确定该往哪个方向发展。

我有一个导致一些性能问题的查询,我不知道如何优化它。

查询实际上很简单:

SELECT transactions.* FROM transactions
LEFT OUTER JOIN companies ON "companies"."id" = "transactions"."company_id"
WHERE companies.code ILIKE '%777%'
ORDER BY transactions.id desc LIMIT 10

我想查找名称中包含 777 的公司的所有交易。数据库中有大约 2000 万笔交易和大约 200 家公司。

即使我们的 LIMIT 为 10,查询当前也会超时。我相信这是因为 ILIKE 没有使用索引,所以它非常慢。

这是否是您可能希望将 WHERE 过滤器添加到 JOIN 的实例?我已经对此进行了测试,如果找到记录,它可以快速运行。如果没有找到记录,它会再次超时。

我们应该研究一种可以提高速度的索引吗?

4

2 回答 2

0

您可以尝试 EXISTS 条件,因为您不需要公司表中的任何列:

SELECT tr.* 
FROM transactions tr
WHERE exists (select *  
              from companies c 
              where c.id = tr.company_id 
                and c.code ILIKE '%777%')
ORDER BY tr.id desc 
LIMIT 10

但最终,这order by可能是这里的瓶颈。例如,如果返回 1000 万个事务,那么对这 1000 万行进行排序将需要一些时间。

于 2021-11-17T15:46:23.487 回答
0

一个EXPLAIN查询会很有帮助。也就是说,我不认为 ILIKE 在这里成为瓶颈,而是对事务表的扫描。随后是潜在的大型ORDER BY排序操作

尽管(我认为)系统已经自动执行此操作,但让我们拆分功能并通过使用(索引)临时表手动强制操作顺序。

类似这样的东西:

SELECT id
  INTO TEMPORARY TABLE matching_companies
  FROM companies 
 WHERE companies.code ILIKE '%777%';
 
CREATE UNIQUE INDEX idx_matching_companies_id ON matching_companies (id);

SELECT t.* 
  FROM transactions t
  JOIN matching_companies c
    ON c."id" = t."company_id"
ORDER BY t.id desc LIMIT 10;

假设很少有公司符合 777 的要求,这表明 company_id 上的事务表上的索引应该在这里派上用场

如果简单地添加索引可能已经加快了您的原始查询,我不会感到太惊讶,因为恕我直言,系统会将查询拆分为几乎相同的操作(减去idx_matching_companies_id可能)

于 2021-11-18T13:02:07.987 回答