1

我有一张有 1100 万条记录的大桌子。我想要一张唱片。

SELECT * 
FROM "PRD".events_log 
WHERE plc_time < '2012-11-19 14:00' 
  AND ((event_type_id IN (1,51) 
       AND machine_id = 1 
       AND island_id = 88) 
   OR (event_type_id IN (2000,2001) 
       AND machine_id=88)) 
ORDER BY plc_time desc 
LIMIT 1

订购此查询的成本很高,因为我不限制双方的 plc_time。我不能限制这个,所以我可以加快这个速度吗?

我有重要字段的索引,所以缺少它不是问题。

此查询是函数 pl/pgsql 中的其他几个查询之一。

我听说过一些关于光标的东西,但我不知道如何使用它。

这是解释分析这个查询:

“限制(成本=4719.97..4719.97 行=1 宽度=850)(实际时间=6074.900..6074.901 行=1 循环=1)”
“ -> 排序(成本=4719.97..4720.49 行=208 宽度=850)(实际时间=6074.897..6074.897 行=1 循环=1)”
“排序键:plc_time”
“排序方法:top-N heapsort 内存:17kB”
“ -> events_log 上的位图堆扫描(成本=50.07..4718.93 行=208 宽度=850)(实际时间=248.306..6068.046 行=6911 循环=1)”
" 重新检查条件:(((machine_id = 1) AND (event_type_id = ANY ('{1,51}'::integer[]))) OR ((machine_id = 88) AND (event_type_id = ANY ('{2000,2001 }'::整数[]))))”
“过滤器:((plc_time BitmapOr(成本=50.07..50.07 行=1246 宽度=0)(实际时间=244.710..244.710 行=0 循环=1)”
“ -> fki_events_type_fk 上的位图索引扫描(成本=0.00..24.98 行=623 宽度=0)(实际时间=238.529..238.529 行=832699 循环=1)”
" 索引条件:((machine_id = 1) AND (event_type_id = ANY ('{1,51}'::integer[])))"
“ -> fki_events_type_fk 上的位图索引扫描(成本=0.00..24.98 行=623 宽度=0)(实际时间=6.177..6.177 行=6869 循环=1)”
“索引条件:((machine_id = 88) AND (event_type_id = ANY ('{2000,2001}'::integer[])))”
“总运行时间:6075.175 毫秒”

并分析表:

INFORMACJA: analizowanie "PRD.events_log"
INFORMACJA:“events_log”:przeskanowano 30000 z 158056 stron,zawierających 2369701 żywych wierszy i 71270 martwych wierszy;30000 wierszy w przykładzie, 12488167 szacowanych wszystkich wierszy
Zapytanie zostało wykonane w 52203 ms i nie zwróciło żadnych wyników。

快速翻译:
从 158056 页中扫描了 3000 个,包含:
2369701 活行和 71270 死行。
例如 30000 行,12488167 估计所有行
4

2 回答 2

1

只是查看查询的一个想法:如果您为 event_type 的选择创建一个子查询怎么办?我可以想象排序花费的时间最多,并且在使用子查询时可能会减少必须处理的数据:

select * from "prd".events_log where plc_time < '2012-11-19 14:00' and id in (
 select e.id from "prd".events_log e where (e.event_type_id IN (1,51) etc...
   AND machine_id=88))) ORDER BY plc_time desc LIMIT 1;

另一种解决方案可能是使用另一个子查询最小化内存中的数据:

select * from "prd".events_log where id in (select e.id from etc..);

整个想法是您只在需要时才要求行的其余部分。

带有光标的代码如下所示:

create or replace function use_lock returns int as $$
declare
 cur refcursor;
 rec RECORD;
begin
 open cur for select .... ;
 loop
  fetch cur into rec;
  exit when not found;
  ..business logic working on the record.
 end loop;
 close cur;
END;
$$ LANGUAGE PLPGSQL STABLE;

希望这可以帮助,

洛克

于 2012-11-27T07:55:33.420 回答
0

尝试在plc_time. 它将加快查询速度。

如果没有索引,plc_time它将始终对表进行全面扫描,因为ORDER BY plc_time.

UPD:试试这张ANALYZE桌子。详细信息在这里http://www.postgresql.org/docs/current/static/sql-analyze.html

于 2012-11-23T13:59:21.930 回答