1

“名称”是一个包含或多或少 100 万行的表。我已经尝试过这个请求,但它永远不会结束。是否有避免“进入”的问题?

update name 
   set name_val = true 
where name_pk in (select max (name_pk) 
                  from name 
                  group by foreign_key_pk);

如果有必要,我不反对触发器。

查询计划:

"Nested Loop  (cost=26073.59..26310.38 rows=200 width=54)"
"  ->  HashAggregate  (cost=26073.59..26075.59 rows=200 width=4)"
"        ->  HashAggregate  (cost=23122.82..24598.20 rows=118031 width=12)"
"              ->  Seq Scan on name  (cost=0.00..19956.21 rows=633321 width=12)"
"  ->  Index Scan using name_pk on name  (cost=0.00..1.16 rows=1 width=54)"
"        Index Cond: (public.name.name_pk = (max(public.name.name_pk)))"

2个指标:

CREATE INDEX link_name_foreign_key_pk
  ON name
  USING btree
  (foreign_key_pk);

CREATE UNIQUE INDEX name_pk
  ON name
  USING btree
  (name_pk);

谢谢。

4

1 回答 1

3

像这样创建一个多列索引(很像评论中已经建议的@a_horse):

CREATE INDEX name_foo_id ON name (foreign_key_pk, name_pk DESC)

DESCmake 只是稍微快一点。Postgres 几乎可以以同样快的速度向后扫描索引。但是使用多列索引可能会变得棘手。

并将此替代语法用于UPDATE

UPDATE name n
SET    name_val = TRUE
FROM  (
    SELECT max(name_pk) AS max_pk
    FROM   name 
    GROUP  BY foreign_key_pk
  ) x
WHERE n.name_pk = x.max_pk
AND   name_val IS DISTINCT FROM TRUE;

IN对于较大的集合,往往是最慢的解决方案。AJOIN应该更快。

附加WHERE子句AND name_val IS DISTINCT FROM TRUE避免了(昂贵的)空更新。

反半连接NOT EXISTS也可能是性能王冠的竞争者:

UPDATE name n
SET    name_val = TRUE
WHERE  NOT EXISTS (
   SELECT 1
   FROM   name
   WHERE  foreign_key_pk = n.foreign_key_pk
   AND    name_pk > n.name_pk
   )
AND    name_val IS DISTINCT FROM TRUE;
于 2013-06-10T16:22:59.557 回答