我正在使用PostgreSQL9.3开发一个项目。我使用下面的查询来说明选择性估计错误如何导致使用PostgreSQL8.3在TPC-H工作负载上查询执行时间多倍增加。
select
n_name,
sum(l_extendedprice * (1 - l_discount)) as revenue
from
customer,
orders,
lineitem,
supplier,
nation,
region
where
c_custkey = o_custkey
and l_orderkey = o_orderkey
and l_suppkey = s_suppkey
and c_nationkey = s_nationkey
and s_nationkey = n_nationkey
and n_regionkey = r_regionkey
and (r_name='ASIA' or r_name='AFRICA')
and o_orderdate >= date '1994-01-01'
and o_orderdate < date '1994-01-01' + interval '1 year'
and l_shipdate <= l_receiptdate
and l_commitdate <= l_shipdate + integer '90'
and l_extendedprice <= 20000
and c_name like '%r#00%'
and c_acctbal <=2400
group by
n_name
order by
revenue desc
问题是PostgreSQL8.3正在选择一个涉及大量NestedLoop连接的计划,因为对lineitem和客户的选择性估计是大错误的。我认为这主要是由于LIKE模式匹配。但最佳计划应该是使用Hash Joins。
最近我为我的项目升级到PostgreSQL9.3并观察到上述查询不再给出错误的计划。我花了一些时间试图在TPC-H 1GB数据上找到一个大基数估计错误的查询,直到现在都没有成功。是否有任何PostgreSQL极客知道TPC-H基准测试的现成查询或任何查询以显示PostgreSQL9.3中的基数估计错误
答案 0 :(得分:1)
这是回答comment by @Twelfth以及问题本身。
Three quotes from this chapter in the manual:
"Controlling the Planner with Explicit JOIN
Clauses"
明确的内部联接语法(
INNER JOIN
,CROSS JOIN
或简单的JOIN
) 在语义上与列出FROM
中的输入关系相同,所以它 不限制连接顺序。
...
强制规划人员遵循显式列出的连接顺序
JOIN
s,将join_collapse_limit
运行时参数设置为1.(其他 可能的值将在下面讨论。)
...
以这种方式约束计划者的搜索是一种有用的技术 既可以减少计划时间,也可以指导计划者 良好的查询计划。
大胆强调我的。相反,您可以滥用相同的方法将查询计划程序指向错误的查询计划,以用于测试目的。阅读整个手册页。它应该是有用的。
此外,您可以逐个disabling alternative methods强制嵌套循环(仅在您的会话中最好)。像:
SET enable_hashjoin = off;
等。
关于检查和设置参数:
一种显而易见的方法是禁用autovacuum并在表中添加/删除行。然后查询计划程序正在处理过时的统计信息。请注意,其他一些命令也会更新统计信息。
统计信息存储在目录表pg_class
和pg_statistics
中。
SELECT * FROM pg_class WHERE oid = 'mytable'::regclass;
SELECT * FROM pg_statistic WHERE starelid = 'mytable'::regclass;
这引出了另一种选择。您可以在这两个表中伪造条目。需要超级用户权限 作为一个新手,你不会打击我,但是对一般公众的警告:如果你在目录表中破坏了某些东西,你的数据库(集群)可能会瘫痪。你被警告了。