优化 SQL 对 table 的 1000 万行查询:永无止境的查询
Optimizing SQL query on table of 10 million rows: neverending query
我有两个表:
CREATE TABLE routing
(
id integer NOT NULL,
link_geom geometry,
source integer,
target integer,
traveltime_min double precision,
CONSTRAINT routing_pkey PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
CREATE INDEX routing_id_idx
ON routing
USING btree
(id);
CREATE INDEX routing_link_geom_gidx
ON routing
USING gist
(link_geom);
CREATE INDEX routing_source_idx
ON routing
USING btree
(source);
CREATE INDEX routing_target_idx
ON routing
USING btree
(target);
和
CREATE TABLE test
(
link_id character varying,
link_geom geometry,
id integer NOT NULL,
.. (some more attributes here)
traveltime_min double precision,
CONSTRAINT id PRIMARY KEY (id),
CONSTRAINT test_link_id_key UNIQUE (link_id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE test
OWNER TO postgres;
我正在尝试应用以下查询:
update routing
set traveltime_min = t2.traveltime_min
from test t2
where t2.id = routing.id
两个表都有近 1000 万行。问题是此查询无休止地运行。 'EXPLAIN' 显示的是:
Update on routing (cost=601725.94..1804772.15 rows=9712264 width=208)
-> Hash Join (cost=601725.94..1804772.15 rows=9712264 width=208)
Hash Cond: (routing.id = t2.id)"
-> Seq Scan on routing (cost=0.00..366200.23 rows=9798223 width=194)"
-> Hash (cost=423414.64..423414.64 rows=9712264 width=18)"
-> Seq Scan on test t2 (cost=0.00..423414.64 rows=9712264 width=18)"
我无法理解是什么导致了如此缓慢的响应问题。
有没有可能是服务器设置的问题?问题是我使用默认的 postgrSQL 9.3 设置。
在 运行 和 UPDATE
之前删除 routing
上的所有索引,然后再添加它们。这将带来巨大的进步。
在您 运行 UPDATE
的会话中将 work_mem
设置为高。这将有助于散列。
将 shared_buffers
设置为可用内存的 ¼,但不超过 1GB。
- 如果不是所有的行实际上都被 UPDATE 更改(如果得到的值与它们的值相同),您应该避免这些幂等更新。
- 如果您希望查询影响每一行,那么查询计划并不重要。 [除了,也许,对于哈希表溢出的情况...]
-- these could be needed if the update would be more selective...
VACUUM analyze routing;
VACUUM analyze test;
UPDATE routing dst
SET traveltime_min = src.traveltime_min
FROM test src
WHERE dst.id = src.id
-- avoid useless updates and row-versions
AND dst.traveltime_min IS DISTINCT FROM src.traveltime_min
;
-- VACUUM analyze routing;
我有两个表:
CREATE TABLE routing
(
id integer NOT NULL,
link_geom geometry,
source integer,
target integer,
traveltime_min double precision,
CONSTRAINT routing_pkey PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
CREATE INDEX routing_id_idx
ON routing
USING btree
(id);
CREATE INDEX routing_link_geom_gidx
ON routing
USING gist
(link_geom);
CREATE INDEX routing_source_idx
ON routing
USING btree
(source);
CREATE INDEX routing_target_idx
ON routing
USING btree
(target);
和
CREATE TABLE test
(
link_id character varying,
link_geom geometry,
id integer NOT NULL,
.. (some more attributes here)
traveltime_min double precision,
CONSTRAINT id PRIMARY KEY (id),
CONSTRAINT test_link_id_key UNIQUE (link_id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE test
OWNER TO postgres;
我正在尝试应用以下查询:
update routing
set traveltime_min = t2.traveltime_min
from test t2
where t2.id = routing.id
两个表都有近 1000 万行。问题是此查询无休止地运行。 'EXPLAIN' 显示的是:
Update on routing (cost=601725.94..1804772.15 rows=9712264 width=208)
-> Hash Join (cost=601725.94..1804772.15 rows=9712264 width=208)
Hash Cond: (routing.id = t2.id)"
-> Seq Scan on routing (cost=0.00..366200.23 rows=9798223 width=194)"
-> Hash (cost=423414.64..423414.64 rows=9712264 width=18)"
-> Seq Scan on test t2 (cost=0.00..423414.64 rows=9712264 width=18)"
我无法理解是什么导致了如此缓慢的响应问题。 有没有可能是服务器设置的问题?问题是我使用默认的 postgrSQL 9.3 设置。
在 运行 和 UPDATE
之前删除 routing
上的所有索引,然后再添加它们。这将带来巨大的进步。
在您 运行 UPDATE
的会话中将 work_mem
设置为高。这将有助于散列。
将 shared_buffers
设置为可用内存的 ¼,但不超过 1GB。
- 如果不是所有的行实际上都被 UPDATE 更改(如果得到的值与它们的值相同),您应该避免这些幂等更新。
- 如果您希望查询影响每一行,那么查询计划并不重要。 [除了,也许,对于哈希表溢出的情况...]
-- these could be needed if the update would be more selective...
VACUUM analyze routing;
VACUUM analyze test;
UPDATE routing dst
SET traveltime_min = src.traveltime_min
FROM test src
WHERE dst.id = src.id
-- avoid useless updates and row-versions
AND dst.traveltime_min IS DISTINCT FROM src.traveltime_min
;
-- VACUUM analyze routing;