http://blog.youkuaiyun.com/hantiannan/article/details/4517192
http://www.cnblogs.com/gaojian/archive/2012/11/08/2759874.html
http://m.oschina.net/blog/135872
http://wgzhao.com/2012/08/21/explaining-the-postgresql-query-optimizer/
http://blog.youkuaiyun.com/java3344520/article/details/5515497
执行计划查看:
从上到下,跟python代码类似,根据缩进查看。
操作关键字:
执行计划运算类型 | 操作说明 | 是否有启动时间 |
---|---|---|
Seq Scan | 扫描表 | 无启动时间 |
Index Scan | 索引扫描 | 无启动时间 |
Bitmap Index Scan | 索引扫描 | 有启动时间 |
Bitmap Heap Scan | 索引扫描 | 有启动时间 |
Subquery Scan | 子查询 | 无启动时间 |
Tid Scan | 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 | 有启动时 |
几种表之间的连接方式:
Nested Loop 循环结合
如果inner内表较小:
for(i=0;i < length(outer); i++)
for(j=0; j < length(inner); j++)
if (outer[i] == inner[j])
output(outer[i],inner[j])
Merge Join 合并结合
sort(outer);
sort(inner);
i=0;
j=0;
save_j=0;
while ( i < length(outer)) {
if (outer[i] == inner[j])
output[outer[i],inner[j])
if (outer[i] >= inner[j] && j < length(inner)){
j++;
if (outer[i] < inner[j])
save_j = j;
else
i++;
j = save_j;
}
}
Hash Join 哈希结合
for (j = 0; j < length(inner); j++) {
hash_key = hash(inner[j]);
append(hash_store(hash_key),inner[j]);
}
for (i = 0; i < length(outer); i++) {
hash_key = hash(outer[i]);
for (j = 0; j < length(hash_store(hash_key]); j++)
if (outer[i] == hash_store[hash_key][j])
output(outer[i],inner[j]);
}
Nested Loop
将所有from部分涉及到的表都进行一次for循环。
举例说明:
demo1:
postgres=# EXPLAIN SELECT relname, nspname FROM pg_class JOIN
postgres-# pg_namespace ON (pg_class.relnamespace=pg_namespace.oid);
QUERY PLAN
-------------------------------------------------------------------------
Hash Join (cost=1.14..16.07 rows=292 width=128)#第1行
Hash Cond: (pg_class.relnamespace = pg_namespace.oid)#第2行
-> Seq Scan on pg_class (cost=0.00..10.92 rows=292 width=68)#第3行
-> Hash (cost=1.06..1.06 rows=6 width=68)#第4行
-> Seq Scan on pg_namespace (cost=0.00..1.06 rows=6 width=68)#第5行
(5 rows)
第1行:是操作关键字hash join ,其下的缩进(距离小于第1行的行)都是对这个hash join解释。
第2行:hash join的条件。
第3行:顺序扫描遍历pg_class表(inner内表),在系统内存中形成一个hash内存块。
第4行:由于第3,4行缩进一样,所以是同级别的。用第3行形成的内存块进行hash运算,其对象是第5行描述的pg_namespace表。
第5行:对pg_namespace表进行顺序扫描遍历。
demo2:
create table tb1_join_1 (id int primary key, info text);
create table tb1_join_2 (id int primary key, info text);
create table tb1_join_3 (id int primary key, info text);
create table tb1_join_4 (id int primary key, info text);
create table tb1_join_5 (id int primary key, info text);
create table tb1_join_6 (id int primary key, info text);
create table tb1_join_7 (id int primary key, info text);
create table tb1_join_8 (id int primary key, info text);
create table tb1_join_9 (id int primary key, info text);
insert into tb1_join_1 select generate_series(1,10), '测试数据';
insert into tb1_join_2 select generate_series(1,100), '测试数据';
insert into tb1_join_3 select generate_series(1,1000), '测试数据';
insert into tb1_join_4 select generate_series(1,10000), '测试数据';
insert into tb1_join_5 select generate_series(1,100000), '测试数据';
insert into tb1_join_6 select generate_series(1,1000000), '测试数据';
insert into tb1_join_7 select generate_series(1,2000000), '测试数据';
insert into tb1_join_8 select generate_series(1,4000000), '测试数据';
insert into tb1_join_9 select generate_series(1,8000000), '测试数据';
postgres=# explain select t1.info, t5.info
from
tb1_join_1 t1,
tb1_join_2 t2,
tb1_join_3 t3,
tb1_join_4 t4,
tb1_join_5 t5,
tb1_join_6 t6,
tb1_join_7 t7,
tb1_join_8 t8,
tb1_join_9 t9
where
t1.id=t2.id and
t2.id=t3.id and
t3.id=t4.id and
t4.id=t5.id and
t5.id=t6.id and
t6.id=t7.id and
t7.id=t8.id and
t8.id=t9.id and
t9.id=10000;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------
Nested Loop (cost=2.72..69.19 rows=1 width=45)
-> Nested Loop (cost=2.29..60.73 rows=1 width=49)
-> Nested Loop (cost=1.86..52.27 rows=1 width=49)
-> Nested Loop (cost=1.43..43.82 rows=1 width=49)
-> Nested Loop (cost=1.00..35.37 rows=1 width=49)
-> Nested Loop (cost=0.71..27.05 rows=1 width=36)
-> Nested Loop (cost=0.43..18.73 rows=1 width=36)
-> Nested Loop (cost=0.15..10.43 rows=1 width=36)
-> Index Scan using tb1_join_1_pkey on tb1_join_1 t1 (cost=0.15..8.17 rows=1 width=36)
Index Cond: (id = 10000)
-> Seq Scan on tb1_join_2 t2 (cost=0.00..2.25 rows=1 width=4)
Filter: (id = 10000)
-> Index Only Scan using tb1_join_3_pkey on tb1_join_3 t3 (cost=0.28..8.29 rows=1 width=4)
Index Cond: (id = 10000)
-> Index Only Scan using tb1_join_4_pkey on tb1_join_4 t4 (cost=0.29..8.30 rows=1 width=4)
Index Cond: (id = 10000)
-> Index Scan using tb1_join_5_pkey on tb1_join_5 t5 (cost=0.29..8.31 rows=1 width=17)
Index Cond: (id = 10000)
-> Index Only Scan using tb1_join_6_pkey on tb1_join_6 t6 (cost=0.42..8.44 rows=1 width=4)
Index Cond: (id = 10000)
-> Index Only Scan using tb1_join_7_pkey on tb1_join_7 t7 (cost=0.43..8.45 rows=1 width=4)
Index Cond: (id = 10000)
-> Index Only Scan using tb1_join_8_pkey on tb1_join_8 t8 (cost=0.43..8.45 rows=1 width=4)
Index Cond: (id = 10000)
-> Index Only Scan using tb1_join_9_pkey on tb1_join_9 t9 (cost=0.43..8.45 rows=1 width=4)
Index Cond: (id = 10000)
(26 rows)
Time: 15.473 ms
postgres=# explain select t1.info, t5.info
postgres-# from
postgres-# tb1_join_1 t1
postgres-# join tb1_join_2 t2 on (t1.id=t2.id)
postgres-# join tb1_join_3 t3 on (t2.id=t3.id)
postgres-# join tb1_join_4 t4 on (t3.id=t4.id)
postgres-# join tb1_join_5 t5 on (t4.id=t5.id)
postgres-# join tb1_join_6 t6 on (t5.id=t6.id)
postgres-# join tb1_join_7 t7 on (t6.id=t7.id)
postgres-# join tb1_join_8 t8 on (t7.id=t8.id)
postgres-# join tb1_join_9 t9 on (t8.id=t9.id)
postgres-# where t9.id=10000;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------
Nested Loop (cost=2.72..69.19 rows=1 width=45)
-> Nested Loop (cost=2.29..60.73 rows=1 width=49)
-> Nested Loop (cost=1.86..52.27 rows=1 width=49)
-> Nested Loop (cost=1.43..43.82 rows=1 width=49)
-> Nested Loop (cost=1.00..35.37 rows=1 width=49)
-> Nested Loop (cost=0.71..27.05 rows=1 width=36)
-> Nested Loop (cost=0.43..18.73 rows=1 width=36)
-> Nested Loop (cost=0.15..10.43 rows=1 width=36)
-> Index Scan using tb1_join_1_pkey on tb1_join_1 t1 (cost=0.15..8.17 rows=1 width=36)
Index Cond: (id = 10000)
-> Seq Scan on tb1_join_2 t2 (cost=0.00..2.25 rows=1 width=4)
Filter: (id = 10000)
-> Index Only Scan using tb1_join_3_pkey on tb1_join_3 t3 (cost=0.28..8.29 rows=1 width=4)
Index Cond: (id = 10000)
-> Index Only Scan using tb1_join_4_pkey on tb1_join_4 t4 (cost=0.29..8.30 rows=1 width=4)
Index Cond: (id = 10000)
-> Index Scan using tb1_join_5_pkey on tb1_join_5 t5 (cost=0.29..8.31 rows=1 width=17)
Index Cond: (id = 10000)
-> Index Only Scan using tb1_join_6_pkey on tb1_join_6 t6 (cost=0.42..8.44 rows=1 width=4)
Index Cond: (id = 10000)
-> Index Only Scan using tb1_join_7_pkey on tb1_join_7 t7 (cost=0.43..8.45 rows=1 width=4)
Index Cond: (id = 10000)
-> Index Only Scan using tb1_join_8_pkey on tb1_join_8 t8 (cost=0.43..8.45 rows=1 width=4)
Index Cond: (id = 10000)
-> Index Only Scan using tb1_join_9_pkey on tb1_join_9 t9 (cost=0.43..8.45 rows=1 width=4)
Index Cond: (id = 10000)
(26 rows)
Time: 6.298 ms