Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PostgreSQL中的查询优化_Sql_Postgresql - Fatal编程技术网

PostgreSQL中的查询优化

PostgreSQL中的查询优化,sql,postgresql,Sql,Postgresql,我有一个非常简单的查询,总运行时间很大。你能告诉我如何优化它吗 以下是解释和分析: 查询: select wpis_id from spoleczniak_oznaczone where etykieta_id in( select tag_id from spoleczniak_subskrypcje where postac_id = 376476 ); 斯波莱茨尼亚克奥扎克区: Column | Type |

我有一个非常简单的查询,总运行时间很大。你能告诉我如何优化它吗

以下是解释和分析:

查询:

select wpis_id from spoleczniak_oznaczone
where etykieta_id in(
  select tag_id
  from spoleczniak_subskrypcje
  where postac_id = 376476
  );
斯波莱茨尼亚克奥扎克区:

 Column    |  Type   |                             Modifiers
-------------+---------+--------------------------------------------------------------------
 id          | integer | not null default nextval('spoleczniak_oznaczone_id_seq'::regclass)
 etykieta_id | integer | not null
 wpis_id     | integer | not null
Indexes:
    "spoleczniak_oznaczone_pkey" PRIMARY KEY, btree (id)
    "spoleczniak_oznaczone_etykieta_id" btree (etykieta_id)
    "spoleczniak_oznaczone_wpis_id" btree (wpis_id)
Foreign-key constraints:
    "spoleczniak_oznaczone_etykieta_id_fkey" FOREIGN KEY (etykieta_id) REFERENCES    spoleczniak_etykiety(id) DEFERRABLE INITIALLY DEFERRED
    "spoleczniak_oznaczone_wpis_id_fkey" FOREIGN KEY (wpis_id) REFERENCES spoleczniak_tablica(id) DEFERRABLE INITIALLY DEFERRED
spoleczniak_subskrypcje:

  Column   |  Type   |                              Modifiers
-----------+---------+----------------------------------------------------------------------
 id        | integer | not null default nextval('spoleczniak_subskrypcje_id_seq'::regclass)
 postac_id | integer | not null
 tag_id    | integer | not null
Indexes:
    "spoleczniak_subskrypcje_pkey" PRIMARY KEY, btree (id)
    "spoleczniak_subskrypcje_postac_id" btree (postac_id)
    "spoleczniak_subskrypcje_postac_tag" btree (postac_id, tag_id)
    "spoleczniak_subskrypcje_tag_id" btree (tag_id)
Foreign-key constraints:
    "spoleczniak_subskrypcje_postac_id_fkey" FOREIGN KEY (postac_id) REFERENCES postac_postacie(id) DEFERRABLE INITIALLY DEFERRED
    "spoleczniak_subskrypcje_tag_id_fkey" FOREIGN KEY (tag_id) REFERENCES spoleczniak_etykiety(id) DEFERRABLE INITIALLY DEFERRED

从查询计划来看,大部分时间似乎都涉及到where子句的in部分。似乎使用了适当的索引

select o.wpis_id 
from spoleczniak_oznaczone o
inner join spoleczniak_subskrypcje s on s.tag_id = o.etykieta_id
where s.postac_id = 376476
…看起来功能相同,但以不同的方式尝试,可能会生成不同的查询计划

另外,正如@wildplasser所说的,确保统计数据是最新的,并且索引已被碎片整理(我自己不知道如何在PostgreSQL中进行碎片整理)


编辑:正如@a_horse_with_no_name在下面的评论中所说的那样,我建议的查询可以返回原始查询无法返回的重复项。不知道你的数据,我不知道它是否会。这是一个需要记住的警告。

从查询计划来看,大部分时间似乎都在计算where子句的in部分。似乎使用了适当的索引

select o.wpis_id 
from spoleczniak_oznaczone o
inner join spoleczniak_subskrypcje s on s.tag_id = o.etykieta_id
where s.postac_id = 376476
…看起来功能相同,但以不同的方式尝试,可能会生成不同的查询计划

另外,正如@wildplasser所说的,确保统计数据是最新的,并且索引已被碎片整理(我自己不知道如何在PostgreSQL中进行碎片整理)


编辑:正如@a_horse_with_no_name在下面的评论中所说的那样,我建议的查询可以返回原始查询无法返回的重复项。不知道你的数据,我不知道它是否会。这是一个需要记住的警告。

您为什么喜欢在中使用
和子查询来:

select wpis_id 
from spoleczniak_oznaczone, spoleczniak_subskrypcje
where etykieta_id = tag_id 
and postac_id = 376476

我想对于查询优化者来说,简单连接可能更简单。

您为什么喜欢在
中使用
,并使用子查询来:

select wpis_id 
from spoleczniak_oznaczone, spoleczniak_subskrypcje
where etykieta_id = tag_id 
and postac_id = 376476
我想对于查询优化者来说,简单连接可能更简单。

这应该是等效的(在大多数情况下,将生成相同的查询计划)

这应该是等效的(在大多数情况下,将生成相同的查询计划)


尝试替换此索引:

"spoleczniak_oznaczone_etykieta_id" btree (etykieta_id)

索引位于
(etykieta\u id,wpis\u id)
。这样,DB就可以只执行索引扫描(而不需要从表中获取整行,这会占用访问时间)

尝试替换此索引:

"spoleczniak_oznaczone_etykieta_id" btree (etykieta_id)


索引位于
(etykieta\u id,wpis\u id)
。这样,DB就可以只执行索引扫描(而不需要从表中获取整行,这会占用访问时间)

请同时添加实际查询。。。。以及生成的查询计划,请。。。您的表有有效的统计数据吗?您是否对数据库设置进行了任何调整?@wildplasser:查询计划就在那里。explain.depesz.com的链接这是哪个Postgres版本?在9.2上,我希望它在index
spoleczniak\u subskrypcje\u postac\u标签上使用仅索引扫描。另外,您的行估计值有点偏离。因此,如果你仔细阅读计划,你可能会发现你的统计数据是错的。运行
真空分析也请添加实际查询。。。。以及生成的查询计划,请。。。您的表有有效的统计数据吗?您是否对数据库设置进行了任何调整?@wildplasser:查询计划就在那里。explain.depesz.com的链接这是哪个Postgres版本?在9.2上,我希望它在index
spoleczniak\u subskrypcje\u postac\u标签上使用仅索引扫描。另外,您的行估计值有点偏离。因此,如果你仔细阅读计划,你可能会发现你的统计数据是错的。运行
真空分析。联接不一定是
条件下的
的替换。我不这么认为
postac\u id
不是唯一的,标签id也不是唯一的。因此,一个
postac_id
可以多次返回相同的
tag_id
,然后连接的结果将不同于
查询中的
结果……我错过了一些东西。你说得对-谢谢!我将对答案进行注释。@a_horse_和_no_name:在这种情况下,您是错的:
in(…)
在主查询中使用子查询之前,从子查询的结果中删除重复项(和空值)。@wildplasser:没错,这就是为什么联接会返回不同的结果。联接不一定是
条件下的
的替代品。我不这么认为
postac\u id
不是唯一的,标签id也不是唯一的。因此,一个
postac_id
可以多次返回相同的
tag_id
,然后连接的结果将不同于
查询中的
结果……我错过了一些东西。你说得对-谢谢!我将对答案进行注释。@a_horse_with_no_name:在这种情况下,您是错的:
in(…)
在主查询中使用子查询之前,会从子查询的结果中删除重复项(和空值)。@wildplasser:没错,这就是为什么联接会返回不同的结果。对于OP:如果您仔细阅读计划,你可以看到你的统计数据是错的。运行
真空分析在两个表上。我做了。在运行该查询之前。似乎不合逻辑:子查询中估计的行数仍然是非常错误的。对OP:如果仔细阅读计划,您可以看到您的统计数据已关闭。运行
真空分析在两个表上。我做了。在运行该查询之前。似乎不合逻辑:子查询中估计的行数仍然严重错误。速度更快,但不够快(原始查询约800毫秒,在该索引更改后约500毫秒)。能否附加带缓冲区参数的解释计划?您的查询返回>500.000行,这可能是原因。它现在确实执行仅索引扫描,但需要循环23次。spoleczniak_subskrypcje中的一对
(postac_id,tag_id)
不应该是唯一的吗?如果我没弄错的话,这张表是供人们订阅标签的,对吗?如果这是真的,那么您可以在(…)中尝试@simonatrcl query-replace
w