Postgresql:选择6M行 - 需要5分钟?

时间:2016-01-17 01:42:34

标签: performance postgresql indexing

当我从下表中选择(包含6个百万行)时,需要5分钟才能完成以下声明:

SELECT * FROM public.matchmsg order by tradeid desc

我做错了什么?

表格定义

CREATE TABLE public.matchmsg
(
  id bigint NOT NULL DEFAULT nextval('matchmsg_id_seq'::regclass),
  tradeid bigint NOT NULL,
  matchdate timestamp with time zone,
  price double precision NOT NULL,
  size double precision NOT NULL,
  issell boolean NOT NULL,
  CONSTRAINT matchmsg_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE,
  autovacuum_enabled=true
);
ALTER TABLE public.matchmsg
  OWNER TO mb;

CREATE UNIQUE INDEX tradeid_idx
  ON public.matchmsg
  USING btree
  (tradeid);

更新1:

EXPLAIN ANALYSE SELECT * FROM public.matchmsg;

"Seq Scan on matchmsg  (cost=0.00..117720.03 rows=6000103 width=41) (actual time=0.041..837.495 rows=6000102 loops=1)"
"Planning time: 1.769 ms"
"Execution time: 914.932 ms"

查询是否应该在117秒内执行?

更新2:

EXPLAIN ANALYSE SELECT * FROM public.matchmsg order by tradeid

"Index Scan using tradeid_idx on matchmsg  (cost=0.43..278622.57 rows=6177667 width=41) (actual time=0.172..1465.935 rows=6177670 loops=1)"
"Planning time: 0.246 ms"
"Execution time: 1553.377 ms"

更新3:

要获得正确和正确的答案,你还必须提出正确的问题......也许我没有......我意识到只选择6M行并没有多大意义......但事实上我做了 - 我不明白为什么我的电脑如此缓慢地给我一个正确的反应(我仍然不 - 无论数据库,用户界面还是什么 - 我认为5分钟太慢 - 我使用Postgres自己的原生工具:PG企业M.或PG pgAdminIII - 它们完全相同)。什么工具更快/更好,你们用什么用Postgresql?

我现在也意识到索引没有任何帮助 - 当我选择所有行和所有列时。

我试图运行CLUSTER语句 - 但它没有改变任何东西 - 据我所知......?

与6M行有什么关系?好吧 - 我会随着时间的推移用算法/模式做很多不同的分析...所以取决于我将需要的数学/表达式以及计算ect的难度/难度......我想我有2个选项从这里:

要么通过DB中的SQL执行所有需要的数学运算,要么将1000行(只有某些列/ s)加载到我的nodejs代码中,对给定的加载数据进行数学运算...遍历整个数据库。

对于您的信息,以下声明的执行方式如下:

select SUM(price) from matchmsg --> about 1 sec!

SELECT tradeid FROM matchmsg order by tradeid asc limit 1000 offset 5000000 --> about 1 sec!

我也尝试过执行

"SELECT * FROM matchmsg"

在nodeJS内部 - 但是在30秒左右之后崩溃 - 出现错误desc:

"FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory".

但更有趣的是:

"SELECT tradeid FROM matchmsg" --> 7 sec!

我甚至可以选择结果集[5000000]并在我的nodeJS应用程序内的7秒内获得该位置的交易...

所有这些事实都将在一天结束时全部结束 - 我只需要了解真正的数学,以了解要走哪条路......

2 个答案:

答案 0 :(得分:0)

这是正常行为。在这种情况下,主要问题通常是用户必须等待很多事实。在整个数据加载过程中,您可能会考虑重复发送数据块,以显示数据的一部分。此外,您可能会考虑使用分页,这或多或少是一个标准,但这样的任务的等待时间是很正常的。

答案 1 :(得分:0)

您应该使用EXPLAIN ANALYZE条款向SELECT显示ORDER BY。你可能会看到的是索引没有被使用。由于排序会占用有序结果集查询中的大部分时间,因此未排序的SELECT不会提供任何信息来解决您的问题。 (关于117秒的执行时间:我认为你指的是cost=0.00..117720.03,这是任意单位成本的相对衡量标准,具体取决于postgresql.conf中的设置;它与...无关时间或任何其他物理财产。)

默认情况下,索引的结束顺序为ASC,您的查询需要DESC结束顺序的行。因此,要么将索引更改为使用降序,要么为此特定查询创建其他索引:

CREATE UNIQUE INDEX tradeid_idx_desc
  ON public.matchmsg
  USING btree
  (tradeid DESC);

但即使这样,时间也不会减少,因为你要求表中的所有行,所以不会使用索引,但见下文。

另一种方法是使用上面的索引CLUSTER表。这将导致表的一次性物理排序。如果不经常更新行,那么这将显着提高您感兴趣的查询的速度。在新行的一定数量的插入之后,排序速度将降低,因为PG不维护群集,因此您应该定期{ {1}}保持表现的表格。

仿形

看到不同海报之间的讨论,在没有OP的情况下,我重新创建了OP表并运行了各种感兴趣的查询。

表格完全相同。 CLUSTER声明:

INSERT

由于INSERT INTO matchmsg (tradeid, matchdate, price, size, issell) SELECT (random() * 4100000000000000000)::bigint, now(), 3.23, 12.2, true FROM generate_series(1, 6000103); 的随机值分配,ASCDESC的索引都不是UNIQUE

tradeid

简单patrick@puny:~$ psql -d test psql (9.5.0, server 9.4.5) Type "help" for help. test=# EXPLAIN ANALYZE SELECT * FROM matchmsg; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------- Seq Scan on matchmsg (cost=0.00..116076.90 rows=6000090 width=37) (actual time=0.017..637.483 rows=6000103 loops=1) Planning time: 0.601 ms Execution time: 854.207 ms (3 rows) test=# EXPLAIN ANALYZE SELECT * FROM matchmsg ORDER BY tradeid DESC; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------- Index Scan using tradeid_idx_desc on matchmsg (cost=0.43..380121.64 rows=6000090 width=37) (actual time=0.056..15836.728 rows=6000103 loops=1) Planning time: 0.234 ms Execution time: 16160.661 ms (3 rows) test=# CLUSTER matchmsg USING tradeid_idx_desc; CLUSTER test=# EXPLAIN ANALYZE SELECT * FROM matchmsg ORDER BY tradeid DESC; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------ Index Scan using tradeid_idx_desc on matchmsg (cost=0.43..380121.84 rows=6000103 width=37) (actual time=0.029..1158.271 rows=6000103 loops=1) Planning time: 0.289 ms Execution time: 1377.929 ms (3 rows) 提供与OP相同的性能指标(这是一个简单的网络,PG在一台单独的机器上运行)。由于排序,SELECT *查询确实使用 ORDER BY索引,但需要16秒。在降序索引上DESC之后,查询时间减少了12倍(给定或接受)。