我有一个关于PostgreSQL如何执行查询的确切理解的问题。因为它是基于行的,它不应该不管你是否有一个查询像Select * from lineitem
或Select l_orderkey from lineitem
性能明智?此外,为什么Select count(*) from lineitem
和Select * from lineitem
之间的测量时间存在差异,因为在这两种情况下都必须扫描整个表?我是这样衡量性能的:
long starttime=System.CurrenMillis();
Statement a = conn.createStatement();
a.setFetchsize(10000);
Resultset rs = a.executeQuery(Query);
while(rs.next()){}
long endTime=System.currentMillis();
System.out.println((endTime-starttime));
我必须设置一个读取大小,否则会有一个Java堆空间错误,因为表是相当大的。此外,我还试图测量与水平分区表的差异。为此,我按orderstatus='O'拆分表order,得到两个大小相同的表(ordersO, ordersF)。当比较查询Select * from ordersO
和Select * from orders where o_orderstatus='O'
时,我期望分区上的第一个查询只需要一半的时间,因为它只包含一半的tupel?但事实并非如此,测量的时间或多或少相等。
提前感谢您!
这里有几个问题
SELECT col FROM tab
是否优于SELECT * FROM tab
?
是的,有两个原因:
-
PostgreSQL不需要从行中提取所有列。如果该列位于列列表的前面,那么这显然是一个胜利。但是我们也赢了,因为我们不需要"de-toast"那些存储在TOAST表中的超大属性。
-
您必须向客户端传输更少的数据,并且客户端必须处理更少的数据。
为什么SELCT count(*) FROM tab
比SELECT * FROM tab
快?
主要是因为它不需要向客户端传输大量数据。此外,它必须对服务器上的每个表行执行更少的处理。
为什么SELECT * FROM tab_42
和SELECT * FROM tab WHERE partkey = 42
速度一样快?
这是因为分区修剪。如果分区键在WHERE
子句中,PostgreSQL将限制扫描到相应的表分区。