->
表示一个子动作width=0
是表示只获取行的位置,没有读取数据,开始读数据后width肯定大于0EXPLAIN
用于理解和优化SQL
查询,它接受SELECT …
、UPDATE …
或DELETE …
之类的sql
命令并返回查询计划,查询计划详细说明了执行sql
所采取的方法。
Explaining → 执行计划运算类型Seq Scan: 扫描表。Index Scan: 索引扫描。Bitmap Index Scan:索引扫描。Bitmap Heap Scan: 索引扫描。Subquery Scan: 子查询。Tid Scan:ctid = 以CTID为查询条件。Function Scan: 函数扫描。Nested Loop: 循环连接。Merge Join: 排序合并连接。Hash Join: 哈希连接。Sort: 排序,ORDER BY操作。Hash: 哈希运算。Result: 函数扫描,和具体的表无关。Unique: DISTINCT,UNION操作。Limit: LIMIT,OFFSET操作。有Aggregate: count, sum,avg, stddev集约函数。Group: GROUP BY分组操作。Append: UNION操作。Materialize: 子查询。SetOp: INTERCECT,EXCEPT
下面结合以下实例讲解一个执行计划:
EXPLAIN ANALYZE SELECT *
FROM tenk1 t1, tenk2 t2
WHERE t1.unique1 < 100 AND t1.unique2 = t2.unique2 ORDER BY t1.fivethous;QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------Sort (cost=717.34..717.59 rows=101 width=488) (actual time=7.761..7.774 rows=100 loops=1)Sort Key: t1.fivethousSort Method: quicksort Memory: 77kB-> Hash Join (cost=230.47..713.98 rows=101 width=488) (actual time=0.711..7.427 rows=100 loops=1)Hash Cond: (t2.unique2 = t1.unique2)-> Seq Scan on tenk2 t2 (cost=0.00..445.00 rows=10000 width=244) (actual time=0.007..2.583 rows=10000 loops=1)-> Hash (cost=229.20..229.20 rows=101 width=244) (actual time=0.659..0.659 rows=100 loops=1)Buckets: 1024 Batches: 1 Memory Usage: 28kB-> Bitmap Heap Scan on tenk1 t1 (cost=5.07..229.20 rows=101 width=244) (actual time=0.080..0.526 rows=100 loops=1)Recheck Cond: (unique1 < 100)-> Bitmap Index Scan on tenk1_unique1 (cost=0.00..5.04 rows=101 width=0) (actual time=0.049..0.049 rows=100 loops=1)Index Cond: (unique1 < 100)Planning time: 0.194 msExecution time: 8.008 ms
PostgreSQL
建立了一个计划节点的树状结构,代表所采取的不同动作,除第一行以外每个->
表示一个子动作,因此上文的查询结构为:
Sort
└── Hash Join├── Seq Scan└── Hash└── Bitmap Heap Scan└── Bitmap Index Scan
每个节点表示子动作,阅读顺序从后至前。因此上面的执行计划第一步是在tenk_unique1
索引上进行Bitmap Index Scan
。
Bitmap Index Scan on tenk1_unique1 (cost=0.00..5.04 rows=101 width=0) (actual time=0.049..0.049 rows=100 loops=1)Index Cond: (unique1 < 100)
SQL
中的WHERE t1.unique1<100
。PostgreSQL
匹配索引条件unique1<100
的行,行本身不会在这里返回(width=0)
。(cost)
。(cost=0.00…5.04 rows=101 width=0)
中的cost=0.00…5.04
意味着PostgreSQL
希望花费5.04
的任意计算单位来找到这些值,0.00
是该节点起始工作成本(只是启动成本),rows=101
是此索引扫描将返回的估计行数,width
是返回行的估计大小(以字节为单位),width=0
是因为此处只获取数据的实际位置(ctid)
而不是返回行的内容。ANALYZE
选项运行EXPLAIN
,所以查询实际上已执行并且捕获了时间信息。(actual time=0.049…0.049 rows=100 loops=1)
,loops=1
表示索引扫描被执行了1次;rows=100
表示返回了100行;actual time=0.049…0.049
表示此步骤的开始时间是0.049,结束时间0.049,单位为毫秒,因此此实际执行时间是0,实际时间是每次迭代的平均值,可以将值乘以循环次数以获得真实的执行时间。0.049ms/5.04
,成本单位≈0.01ms/每个成本单位
,注意是actual time的结束时间/cost结束成本
。Bitmap Heap Scan on tenk1 t1 (cost=5.07..229.20 rows=101 width=244) (actual time=0.080..0.526 rows=100 loops=1)Recheck Cond: (unique1 < 100)
Step 1
索引扫描的结果传递给Bitmap Heap Scan
操作。在这个节点中,PostgreSQL
取得tenk1
表(别名为t1
)中行的位置,unique1 < 100
从表中取出行。Step 1
计算的值0.01
,意味着大概的预期时间(229.20-5.07) * 0.01≈2.24ms
,但是实际时间为0.526ms
每行,实际时间是大概的预期时间1/4
,这可能是因为成本估算值是一个上限值,并非所有行都需要读取,或者因为重新检查条件始终为真。Bitmap Index Scan
和Bitmap Heap Scan
的组合比从表中顺序读取行(Seq Scan
)要昂贵得多,但由于在这种情况下需要访问的行相对较少,所以速度更快。Hash (cost=229.20..229.20 rows=101 width=244) (actual time=0.659..0.659 rows=100 loops=1)Buckets: 1024 Batches: 1 Memory Usage: 28kB
Step 2(Heap Scan)
的结果中,来自表tenk1
且unique1<100
的行会在读取时插入到内存哈希表中,正如我们从成本上看到的那样,这个步骤完全没有占用运行时间(cost=229.20…229.20)(actual time=0.659…0.659)
。Hash
包含Buckets
和Batches
以及内存使用情况的信息。如果Batches>1
,则还涉及磁盘使用情况,本例中无。内存使用情况通过公式大约为100*244=24.4kB
,接近实际使用的内存28kB
,多出来的部分假设为Hash
密钥本身所占用的内存。-> Hash Join (cost=230.47..713.98 rows=101 width=488) (actual time=0.711..7.427 rows=100 loops=1)Hash Cond: (t2.unique2 = t1.unique2)-> Seq Scan on tenk2 t2 (cost=0.00..445.00 rows=10000 width=244) (actual time=0.007..2.583 rows=10000 loops=1)
PostgreSQL
从tenk2
中读取所有10000
行(别名为t2
),并根据tenk1
的Hash
来检查它们。Hash Join
意味着一个表的行被输入到内存中的Hash
,之后扫描另一个表的行,并根据Hash
探测匹配的值,在第二行为匹配条件Hash Cond: (t2.unique2 = t1.unique2)
。tenk1
和tenk2
中的所有值,所以在哈希连接期间每行的宽度都会增加一倍。(actual time=0.711…7.427)
。Step 4
花费了7.427ms
,占总执行时间的7.427/7.774=95%
。Sort (cost=717.34..717.59 rows=101 width=488) (actual time=7.761..7.774 rows=100 loops=1)Sort Key: t1.fivethousSort Method: quicksort Memory: 77kB
Sort Key: t1.fivethous
排序结果集。quicksort
,Memory
表示排序是在内存上完成的,使用了77kB
大小的内存。当排序所需的内存超过work_mem
参数的大小时,将使用磁盘空间,这将极大影响查询速度。work_mem
大小,以避免使用磁盘空间实际所需空间大小=所需的内存+所需的磁盘空间
Execution time: 8.008 ms
的时间。本文发布于:2024-02-02 12:46:10,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170684917043892.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |