make_one_rel
set_base_rel_sizes
set_base_rel_pathlists
pathlist
字段中。生成基础关系的path:set_base_rel_pathlists,执行后生成的PATH在RelOptInfo数组中保存:
(gdb) p *root->simple_rel_array[1]->pathlist
$37 = {type = T_List, length = 2, max_length = 5, elements = 0x2a2aa40, initial_elements = 0x2a2aa40}
RelOptInfo数组和RTE数组是对应的:
(gdb) p root->simple_rte_array[1]->relid
$40 = 16471
经过set_base_rel_pathlists生成扫描路径,每个基表的RelOptInfo都记录了若干条path,这些基表作为扫描的基础节点,再次基础上继续构造连接物理算子。
standard_join_search用动态规划方法来尝试不同的连接顺序和组合:
make_rel_from_joinlist
standard_join_search
...
// levels_needed = 3 三张表
root->join_rel_level = (List **) palloc0((levels_needed + 1) * sizeof(List *));
root->join_rel_level[1] = initial_rels;
for (lev = 2; lev <= levels_needed; lev++)
{
ListCell *lc;
join_search_one_level(root, lev);
foreach(lc, root->join_rel_level[lev])
{
rel = (RelOptInfo *) lfirst(lc);
generate_partitionwise_join_paths(root, rel);
if (!bms_equal(rel->relids, root->all_query_rels))
generate_useful_gather_paths(root, rel, false);
/* Find and save the cheapest paths for this rel */
set_cheapest(rel);
}
}
score(seq)
, student(seq)
)score(seq)
, course(seq)
) <<<< 第三层选择score(索引)
, Material(course(seq)
))score(覆盖索引)
, Material(course(seq)
))Hash(score(seq), student(seq))
,course(seq)
)drop table student;
create table student(sno int primary key, sname varchar(10), ssex int);
insert into student values(1, 'stu1', 0);
insert into student values(2, 'stu2', 1);
insert into student values(3, 'stu3', 1);
insert into student values(4, 'stu4', 0);
drop table course;
create table course(cno int primary key, cname varchar(10), tno int);
insert into course values(1, 'meth', 10);
insert into course values(2, 'english', 11);
drop table teacher;
create table teacher(tno int primary key, tname varchar(10), tsex int);
insert into teacher values(10, 'te1', 1);
insert into teacher values(11, 'te2', 0);
drop table score;
create table score (sno int, cno int, degree int);
create index idx_score_sno on score(sno);
insert into score values (1, 10, 100);
insert into score values (1, 11, 89);
insert into score values (2, 10, 99);
insert into score values (2, 11, 90);
insert into score values (3, 10, 87);
insert into score values (3, 11, 20);
insert into score values (4, 10, 60);
insert into score values (4, 11, 70);
explain
SELECT *
FROM STUDENT
LEFT JOIN SCORE ON STUDENT.sno = SCORE.sno
LEFT JOIN COURSE ON SCORE.cno = COURSE.cno;