Postgres中的慢查询优化

时间:2019-06-04 10:19:02

标签: sql postgresql query-optimization sql-optimization

我们在使用特定的SQL查询时遇到性能问题,我们正在尝试找出如何在此处进行改进。它的执行时间大约是20-100秒!

这是查询,并进行了解释:

SELECT  "jobs".* FROM "jobs"
  WHERE "jobs"."status" IN (1, 2, 3, 4)
  ORDER BY "jobs"."due_date" ASC
  LIMIT 5;


Limit  (cost=0.42..1844.98 rows=5 width=2642) (actual time=16927.150..18151.643 rows=1 loops=1)
   ->  Index Scan using index_jobs_on_due_date on jobs  (cost=0.42..1278647.41 rows=3466 width=2642) (actual time=16927.148..18151.641 rows=1 loops=1)
         Filter: (status = ANY ('{1,2,3,4}'::integer[]))
         Rows Removed by Filter: 595627
 Planning time: 0.205 ms
 Execution time: 18151.684 ms

我们在AWS RDS上使用PostgreSQL 9.6.11。

在一个表中,我们有约50万行。实现查询的字段为:

  • 到期日期(没有时区的时间戳,可以为null)
  • 状态(整数,不为null)

我们有以下索引:

CREATE INDEX index_jobs_on_due_date ON public.jobs USING btree (due_date)
CREATE INDEX index_jobs_on_due_date_and_status ON public.jobs USING btree (due_date, status)
CREATE INDEX index_jobs_on_status ON public.jobs USING btree (status)
CREATE UNIQUE INDEX jobs_pkey ON public.jobs USING btree (id)

预先感谢您, -杰克

1 个答案:

答案 0 :(得分:1)

对于此查询:

access_token = dataset.iloc[0].to_frame()

“明显”索引位于 Table1.Rows.Clear(); List<Knjiga> knjige = new List<Knjiga>(); XmlDocument doc = new XmlDocument(); doc.Load(Server.MapPath("biblioteka.xml")); foreach (XmlElement el in doc.GetElementsByTagName("knjiga")) { knjige.Add(new Knjiga() { ISBN = el.GetAttribute("ISBN"), Naslov = el.GetAttribute("naslov"), Stanje = Int32.Parse(el.GetAttribute("stanje")), Citano = Int32.Parse(el.GetAttribute("citano")) }); } knjige = knjige.OrderByDescending(d => d.Citano).ToList(); foreach (var knjiga in knjige) { TableRow tr = new TableRow(); // Cells TableCell isbn = new TableCell(); TableCell naslov = new TableCell(); TableCell stanje = new TableCell(); TableCell citano = new TableCell(); isbn.Text = knjiga.ISBN; naslov.Text = knjiga.Naslov; stanje.Text = knjiga.Stanje.ToString(); citano.Text = knjiga.Citano.ToString(); tr.Cells.AddRange(new TableCell[]{ isbn, naslov, stanje, citano}); Table1.Rows.Add(tr); }上。但这可能无济于事。目标是摆脱排序。因此,您可以重写查询并使用索引SELECT j.* FROM "jobs" j WHERE j."status" IN (1, 2, 3, 4) ORDER BY "jobs"."due_date" ASC LIMIT 5;

(status)

每个子查询都应使用复合索引。然后,最后的排序将是(最多)20行,这应该很快)。

编辑:

这里是一个相关的想法,具有相同的索引:

jobs(status, due_date)

这可以将索引用于select j.* from ((select j.* from jobs j where j.status = 1 order by j.due_date asc limit 5 ) union all (select j.* from jobs j where j.status = 2 order by j.due_date asc limit 5 ) union all (select j.* from jobs j where j.status = 3 order by j.due_date asc limit 5 ) union all (select j.* from jobs j where j.status = 4 order by j.due_date asc limit 5 ) ) j order by due_date limit 5; 计算。这可能需要对表进行全表扫描。但是,最终排序将限制为20行,因此消除了最终排序。