Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.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 当内部选择索引条件更快时,Postgres使用哈希连接和Seq扫描_Postgresql_Query Planner - Fatal编程技术网

Postgresql 当内部选择索引条件更快时,Postgres使用哈希连接和Seq扫描

Postgresql 当内部选择索引条件更快时,Postgres使用哈希连接和Seq扫描,postgresql,query-planner,Postgresql,Query Planner,当索引可用时,Postgres在表跟踪上使用更重的Seq扫描。第一个查询是原始尝试,它使用Seq扫描,因此查询速度较慢。我试图用一个内部Select强制进行索引扫描,但postgres用几乎相同的运行时将其转换回相同的查询。最后,我从查询2的内部Select复制了该列表以进行第三次查询。最后,postgres使用了索引扫描,这大大减少了运行时间。第三个查询在生产环境中不可行。什么会导致postgres使用最后一个查询计划 两张桌子都使用了真空吸尘器 桌子 跟踪工作人员id,localdateti

当索引可用时,Postgres在表跟踪上使用更重的Seq扫描。第一个查询是原始尝试,它使用Seq扫描,因此查询速度较慢。我试图用一个内部Select强制进行索引扫描,但postgres用几乎相同的运行时将其转换回相同的查询。最后,我从查询2的内部Select复制了该列表以进行第三次查询。最后,postgres使用了索引扫描,这大大减少了运行时间。第三个查询在生产环境中不可行。什么会导致postgres使用最后一个查询计划

两张桌子都使用了真空吸尘器

桌子 跟踪工作人员id,localdatetime总记录:118664105 项目工人id,项目id总记录:12935 指数 在public.tracking上创建索引跟踪\u worker\u id\u localdatetime\u idx,使用btree worker\u id,localdatetime 询问 从跟踪t.worker\u id=pw.id上的t JOIN project\u worker pw中选择worker\u id,localdatetime,其中project\u id=68475018

从跟踪t中选择worker_id,localdatetime,其中worker_id在从project_worker中选择id,其中project_id=68475018 LIMIT 500

从跟踪t中选择worker_id,localdatetime,其中worker_id位于322016383316007840,…,285702579

。。。替换查询中使用的500个id条目

在另一组500个id上运行相同的查询

Index Scan using tracking_worker_id_localdatetime_idx on tracking t  (cost=0.57..4776714.91 rows=21900980 width=24) (actual time=0.105..5528.109 rows=117838 loops=1)
 "  Index Cond: (worker_id = ANY ('{286237712,286237844,...,216724213}'::bigint[]))"
Planning Time: 2.105 ms
Execution Time: 5534.948 ms

跟踪中工人id的分布似乎非常不均匀。首先,查询3的一个实例中的行数返回的行数是它的另一个实例的5倍多。另一方面,估计的行数是实际行数的100到1000倍。这当然会导致糟糕的计划,尽管这不太可能是全部


跟踪中worker_id的不同值的实际数量是多少:从跟踪中选择countdistinct worker_id?规划者认为这个值是什么:选择n_与pg_stats不同,其中tablename='tracking'和attname='worker\u id'?如果这些值相距很远,并且您强制规划者在alter table tracking alter column worker_id set n_distinct=)中使用更合理的值;分析跟踪;这会改变计划吗?

如果要将PostgreSQL推向嵌套循环联接,请尝试以下操作:

创建可用于仅索引扫描的跟踪索引:

CREATE INDEX ON tracking (worker_id) INCLUDE (localdatetime);
确保经常对跟踪进行真空处理,以便仅索引扫描有效

减少随机页面成本并增加有效缓存大小,以便优化器降低索引扫描的价格,但不使用疯狂的值

确保您对项目工作人员有良好的评估:


第三个查询只是从缓存中读取数据吗?如果您选择500个不同的列表会发生什么?PostgreSQL的哪个版本?要从您的计划中获得更好的信息,请打开track_io_timing并运行EXPLAIN Analysis,BUFFERSPostgreSQL 11。6@jjanes我运行了另一组ID,没有任何缓存的可能性。结果是相似的。由于跟踪表中的数据量,索引扫描显然更快。
Index Scan using tracking_worker_id_localdatetime_idx on tracking t  (cost=0.57..4766798.31 rows=21877360 width=24) (actual time=0.079..29.756 rows=22112 loops=1)
 "  Index Cond: (worker_id = ANY ('{322016383,316007840,...,285702579}'::bigint[]))"
Planning Time: 1.162 ms
Execution Time: 30.884 ms
Index Scan using tracking_worker_id_localdatetime_idx on tracking t  (cost=0.57..4776714.91 rows=21900980 width=24) (actual time=0.105..5528.109 rows=117838 loops=1)
 "  Index Cond: (worker_id = ANY ('{286237712,286237844,...,216724213}'::bigint[]))"
Planning Time: 2.105 ms
Execution Time: 5534.948 ms
CREATE INDEX ON tracking (worker_id) INCLUDE (localdatetime);
ALTER TABLE project_worker ALTER project_id SET STATISTICS 1000;
ANALYZE project_worker;