简单查看postgresql查询的算法改进

时间:2010-07-01 21:34:59

标签: sql algorithm postgresql complexity-theory

高级:我可以根据order by执行此操作group bysum 更快? (PG 8.4,fwiw。,在非小桌子上......想想O(数百万行))

假设我有一个这样的表:

                                 Table "public.summary"
   Column    |       Type        |                      Modifiers
-------------+-------------------+------------------------------------------------------
 ts          | integer           | not null default nextval('summary_ts_seq'::regclass)
 field1      | character varying | not null
 otherfield  | character varying | not null
 country     | character varying | not null
 lookups     | integer           | not null


Indexes:
    "summary_pk" PRIMARY KEY, btree (ts, field1, otherfield, country)
    "ix_summary_country" btree (country)
    "ix_summary_field1" btree (field1)
    "ix_summary_otherfield" btree (otherfield)
    "ix_summary_ts" btree (ts)

我想要的查询是:

select summary.field1,
    summary.country,
    summary.ts,
    sum(summary.lookups) as lookups,
from summary
where summary.country = 'za' and
    summary.ts = 1275177600
group by summary.field1, summary.country, summary.ts
order by summary.ts, lookups desc, summary.field1
limit 100;

(英语:在特定(ts,国家)的前100名field1,其中'topness'是总和 任何匹配行的查找,无论其他字段的值如何)

在算法上 这似乎是一个全表扫描的东西,但我可能会遗漏一些东西。

3 个答案:

答案 0 :(得分:2)

此查询的任何查询计划都必须扫描与WHERE条件匹配的每一行,并按分组条件进行滚动 - 也就是说,工作量与组的输入行数成比例,而不是结果行数。

对于像这样的查询,最有效的查询计划是单个索引扫描。如果你按照这个顺序在(country,ts)上建立索引,这应该是可能的;使用该索引,此表单的每个可能查询都会解析为索引上的连续范围。但是,这仍然需要内存中的排序 - 可以通过不同的索引来避免这种情况。

正如其他人所说,发布执行计划是你最好的选择。

答案 1 :(得分:1)

为了能够提出任何建议,您应该发布查询的执行计划。

“OMG小马”是对的:限制100会将整体结果限制为100行,对个别群组不起作用!

Postgres Wiki中有一篇很好的文章解释了如何发布与慢查询相关的问题:

http://wiki.postgresql.org/wiki/SlowQueryQuestions

答案 2 :(得分:1)

指数(国家,ts)是​​最好的选择(就像尼克约翰逊建议的那样),另外你可能想要提高work_mem如果它没有设置得很高。如果需要,你可以在运行时设置它(如果它非常高,那么建议)。它将有助于保持你的内存,而不是溢出到磁盘(如果发生这种情况)。

要获得真正的帮助,我们需要查看EXPLAIN ANALYZE,将其发布在explain.depesz.com上可以使其非常易读。