当前位置: 首页 > news >正文

做网站的难点是什么档案网站建设图片

做网站的难点是什么,档案网站建设图片,手机软件下载大全,徐州网站建设推广相关 《Postgresql源码#xff08;133#xff09;优化器动态规划生成连接路径的实例分析》 上一篇对路径的生成进行了分析#xff0c;通过make_one_rel最终拿到了一个带着路径的RelOptInfo。本篇针对带volatile函数的排序场景继续分析subquery_planner的后续流程。 subquer… 相关 《Postgresql源码133优化器动态规划生成连接路径的实例分析》 上一篇对路径的生成进行了分析通过make_one_rel最终拿到了一个带着路径的RelOptInfo。本篇针对带volatile函数的排序场景继续分析subquery_planner的后续流程。 subquery_plannergrouping_plannerquery_plannermake_one_rel 上一篇// 后续流程 本篇总结速查 一句话总结带有volatile的投影列会被SORT算子忽略达到先排序在投影计算volatile的效果。 grouping_planner→make_one_rel层层生成path每个path都会带pathtarget不一定是SQL中最后需要的target列表一般都是层层继承上来的。make_one_rel生成的最终path中会忽略volatile函数列交给外层grouping_planner函数处理所以生成的path中的pathtarget都是看不到volatile函数列的。这里一个关键逻辑就path中的pathtarget和make_sort_input_target计算出来列表的是不是一样的 如果是一样的就不加投影节点等后面加sort时create_ordered_paths先加sort在加投影计算顺序就是先排序在拿排序阶段投影计算random函数如果不一样就直接加投影节点后面sort会加到投影上面计算顺序就是先投影计算random函数再排序。 path中的pathtarget会忽略volatile函数。make_sort_input_target中的volatile函数正常也会被忽略掉实例3除非volatile函数就是排序列实例4。 最终效果是投影列有volatile函数的SQL函数非排序列sort节点会忽略这类函数的执行sort结束后在投影节点使用sort的结果集来计算这类函数。 实例3 1 实例简单join 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(20, meth, 10); insert into course values(21, 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, 20, 100); insert into score values (1, 21, 89); insert into score values (2, 20, 99); insert into score values (2, 21, 90); insert into score values (3, 20, 87); insert into score values (3, 21, 20); insert into score values (4, 20, 60); insert into score values (4, 21, 70);explain SELECT STUDENT.sname, COURSE.cname, SCORE.degree FROM STUDENT LEFT JOIN SCORE ON STUDENT.sno SCORE.sno LEFT JOIN COURSE ON SCORE.cno COURSE.cno;QUERY PLAN ------------------------------------------------------------------------------Hash Left Join (cost69.50..110.65 rows2040 width80)Hash Cond: (score.cno course.cno)- Hash Right Join (cost34.75..70.53 rows2040 width46)Hash Cond: (score.sno student.sno)- Seq Scan on score (cost0.00..30.40 rows2040 width12)- Hash (cost21.00..21.00 rows1100 width42)- Seq Scan on student (cost0.00..21.00 rows1100 width42)- Hash (cost21.00..21.00 rows1100 width42)- Seq Scan on course (cost0.00..21.00 rows1100 width42)1.1 subquery_planner→grouping_planner grouping_plannercurrent_rel query_planner(root, standard_qp_callback, qp_extra);current_rel final_target create_pathtarget(root, root-processed_tlist);得到final_target final_target-exprs-elements[0] : {varno 1, varattno 2, vartype 1043} STUDENT.snamefinal_target-exprs-elements[1] : {varno 4, varattno 2, vartype 1043} COURSE.cnamefinal_target-exprs-elements[2] : {varno 2, varattno 3, vartype 23} SCORE.degree if (parse-sortClause)make_sort_input_targetif (activeWindows)...if (have_grouping)...if (parse-hasTargetSRFs)...apply_scanjoin_target_to_paths创建投影节点 /* Apply scan/join target. */scanjoin_target_same_exprs list_length(scanjoin_targets) 1 equal(scanjoin_target-exprs, current_rel-reltarget-exprs);apply_scanjoin_target_to_paths(root, current_rel, scanjoin_targets,scanjoin_targets_contain_srfs,scanjoin_target_parallel_safe,scanjoin_target_same_exprs);继续 if (have_grouping)...if (activeWindows)...if (parse-distinctClause)...if (parse-sortClause)create_ordered_paths创建空的最顶层节点 final_rel fetch_upper_rel(root, UPPERREL_FINAL, NULL);遍历current_rel中所有的path用add_path加入到最顶层节点中。其中limit、rowclock的场景需要特殊处理下。 foreach(lc, current_rel-pathlist)if (parse-rowMarks)create_lockrows_pathif (limit_needed(parse))create_limit_pathadd_path(final_rel, path);grouping_planner函数执行结束最后拼接的final_rel在upper_rels里面记录 pathlist最上层是投影节点 1.2 standard_planner→subquery_planner subquery_planner中后续处理流程 计划生成步骤作用root subquery_planner优化器入口返回PlannerInfo里面记录了一个最终的RelOptInfo相当于一张逻辑表每个ROI都记录了多个path表示不同的计算路径final_rel fetch_upper_rel拿到最终的RelOptInfobest_path get_cheapest_fractional_path在RelOptInfo中选择一个最优的pathtop_plan create_plan→create_plan_recurse根据最优path生成计划 2 实例【简单join】【排序非投影列】【投影列无函数】 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(20, meth, 10); insert into course values(21, 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, 20, 100); insert into score values (1, 21, 89); insert into score values (2, 20, 99); insert into score values (2, 21, 90); insert into score values (3, 20, 87); insert into score values (3, 21, 20); insert into score values (4, 20, 60); insert into score values (4, 21, 70);explain verbose SELECT STUDENT.sname, COURSE.cname, SCORE.degree FROM STUDENT LEFT JOIN SCORE ON STUDENT.sno SCORE.sno LEFT JOIN COURSE ON SCORE.cno COURSE.cno ORDER BY COURSE.cno;QUERY PLAN --------------------------------------------------------------------------------------Sort (cost3.44..3.46 rows8 width19)Output: student.sname, course.cname, score.degree, course.cnoSort Key: course.cno- Hash Left Join (cost2.14..3.32 rows8 width19)Output: student.sname, course.cname, score.degree, course.cnoInner Unique: trueHash Cond: (score.cno course.cno)- Hash Right Join (cost1.09..2.21 rows8 width13)Output: student.sname, score.degree, score.cnoInner Unique: trueHash Cond: (score.sno student.sno)- Seq Scan on public.score (cost0.00..1.08 rows8 width12)Output: score.sno, score.cno, score.degree- Hash (cost1.04..1.04 rows4 width9)Output: student.sname, student.sno- Seq Scan on public.student (cost0.00..1.04 rows4 width9)Output: student.sname, student.sno- Hash (cost1.02..1.02 rows2 width10)Output: course.cname, course.cno- Seq Scan on public.course (cost0.00..1.02 rows2 width10)Output: course.cname, course.cno2.1 grouping_planner grouping_plannercurrent_rel query_planner(root, standard_qp_callback, qp_extra);final_target create_pathtarget(root, root-processed_tlist);if (parse-sortClause)sort_input_target make_sort_input_target(root, final_target, have_postponed_srfs);make_sort_input_target函数的作用 排序列可能不在最终的投影列里面需要特殊处理下。易变函数和成本很高的函数需要再投影列中识别出来先排序在计算。 因为1sort limit场景可以少算一些。因为2易变函数每次算都可能不一样先排序好了再算有利于结果集稳定例如current_timestamp这种期望是排序后给出的每一样的时间都是递增的如果先排序在计算就能得到这种效果。 生成的final_target和sort_input_target相同因为没看到srf函数、易变函数。 final_target同sort_input_targetVar指向列sortgrouprefsfinal_target-exprs-elements[0]varno 1, varattno 2, vartype 1043STUDENT.sname0final_target-exprs-elements[1]varno 4, varattno 2, vartype 1043COURSE.cname0final_target-exprs-elements[2]varno 2, varattno 3, vartype 23SCORE.degree0final_target-exprs-elements[3]varno 4, varattno 1, vartype 23COURSE.cno1 grouping_planner继续执行开始生成排序path ...if (parse-sortClause)current_rel create_ordered_paths(root,current_rel,final_target,final_target_parallel_safe,have_postponed_srfs ? -1.0 :limit_tuples);grouping_planner→create_ordered_paths create_ordered_paths// 创建一个排序节点ordered_rel fetch_upper_rel(root, UPPERREL_ORDERED, NULL);// 拿到path入口目前顶层是T_ProjectionPath就一个节点foreach(lc, input_rel-pathlist)// 判断input_path-pathkeys是不是有序的// 因为现在计划树是hashjoin每一列都是无序的所以input_path-pathkeys是空的需要排序is_sorted pathkeys_count_contained_in(root-sort_pathkeys, input_path-pathkeys, presorted_keys);if (is_sorted)sorted_path input_path;elsesorted_path (Path *) create_sort_path(root,ordered_rel,input_path,root-sort_pathkeys,limit_tuples); 输入的path顶层节点是project本来没有带pathkeys信息这里创建一个sort节点放在上面加入pathkey信息。但生成的sortpath没看到排序列的信息排序信息在基类path的pathkeys中。 sorted_path { path { type T_SortPath, pathtype T_Sort, parent 0x2334030, pathtarget 0x2333ef0, param_info 0x0, parallel_aware false, parallel_safe true, parallel_workers 0, rows 8, startup_cost 3.4437500000000005, total_cost 3.4637500000000006, pathkeys 0x232e018}, subpath 0x2333a00}T_PathKey每个pathkey排序列都对应了一个T_EquivalenceClassT_EquivalenceClass中记录了排序的具体信息。 { type T_PathKey, pk_eclass 0x232bf88, pk_opfamily 1976, pk_strategy 1, pk_nulls_first false}T_EquivalenceClass中的ec_members记录了排序列信息Var{varno 4, varattno 1} { type T_EquivalenceClass, ec_opfamilies 0x232ddf8, // List{ 1976 }ec_collation 0, ec_members 0x232df48, // List { EquivalenceMember }// EquivalenceMember{// type T_EquivalenceMember, // em_expr 0x232de68, Var{varno 4, varattno 1}// em_relids 0x232de48, // em_is_const false, // em_is_child false, // em_datatype 23, // em_jdomain 0x2329158, em_parent 0x0}ec_sources 0x0, ec_derives 0x0, ec_relids 0x232df28,ec_has_const false, ec_has_volatile false, ec_broken false, ec_sortref 1, ec_min_security 4294967295, ec_max_security 0, ec_merged 0x0}生成排序节点后的计划 sort节点的target是四列虽然sql只写了三列但有一列是排序需要的也会加到pathtarget中。 3 实例【简单join】【排序非投影列】【投影列中有volatile函数】 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(20, meth, 10); insert into course values(21, 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, 20, 100); insert into score values (1, 21, 89); insert into score values (2, 20, 99); insert into score values (2, 21, 90); insert into score values (3, 20, 87); insert into score values (3, 21, 20); insert into score values (4, 20, 60); insert into score values (4, 21, 70);explain verbose SELECT STUDENT.sname, random(), SCORE.degree FROM STUDENT LEFT JOIN SCORE ON STUDENT.sno SCORE.sno LEFT JOIN COURSE ON SCORE.cno COURSE.cno ORDER BY COURSE.cno;QUERY PLAN --------------------------------------------------------------------------------------------Result (cost3.44..3.56 rows8 width21)Output: student.sname, random(), score.degree, course.cno- Sort (cost3.44..3.46 rows8 width13)Output: student.sname, score.degree, course.cnoSort Key: course.cno- Hash Left Join (cost2.14..3.32 rows8 width13)Output: student.sname, score.degree, course.cnoInner Unique: trueHash Cond: (score.cno course.cno)- Hash Right Join (cost1.09..2.21 rows8 width13)Output: student.sname, score.degree, score.cnoInner Unique: trueHash Cond: (score.sno student.sno)- Seq Scan on public.score (cost0.00..1.08 rows8 width12)Output: score.sno, score.cno, score.degree- Hash (cost1.04..1.04 rows4 width9)Output: student.sname, student.sno- Seq Scan on public.student (cost0.00..1.04 rows4 width9)Output: student.sname, student.sno- Hash (cost1.02..1.02 rows2 width4)Output: course.cno- Seq Scan on public.course (cost0.00..1.02 rows2 width4)Output: course.cno3.1 grouping_planner→make_one_rel生成的RelOptInfo→reltarget make_one_rel前 准备连接的RelOptInfo在simple_rel_array数组中这里关注下三个RelOptInfo的reltarget (gdb) plist root-simple_rel_array[1]-reltarget-exprs $67 2 $68 {ptr_value 0x3083218, int_value 50868760, oid_value 50868760, xid_value 50868760} $69 {ptr_value 0x30ab8b8, int_value 51034296, oid_value 51034296, xid_value 51034296} (gdb) p root-simple_rte_array[1]-relid $70 16564root→simple_rel_array[i]simple_rel_array[i]→reltarget-exprsrelid1varno 1, varattno 2, vartype 104316564 student.sname1varno 1, varattno 1, vartype 2316564 student.sno2varno 2, varattno 3, vartype 2316579 score.degree2varno 2, varattno 1, vartype 2316579 score.cno2varno 2, varattno 2, vartype 2316579 score.sno4varno 4, varattno 1, vartype 2316569 course.cno SELECT STUDENT.sname, random(), SCORE.degree FROM STUDENT LEFT JOIN SCORE ON STUDENT.sno SCORE.sno LEFT JOIN COURSE ON SCORE.cno COURSE.cno ORDER BY COURSE.cno;make_one_rel生成后 final_rel-reltarget-exprs列1varno 1, varattno 2, vartype 1043投影第1列STUDENT.sname2varno 2, varattno 3, vartype 23投影第3列SCORE.degree3varno 4, varattno 1, vartype 23排序列COURSE.cno 3.2 grouping_planner→make_sort_input_target规律v函数生成排序target final_target create_pathtarget(root, root-processed_tlist);拿到的final_target final_targetVar / FuncExpr指向列sortgrouprefsfinal_target-exprs-elements[0]varno 1, varattno 2, vartype 1043STUDENT.sname0final_target-exprs-elements[1]funcid 1598, funcresulttype 701random()0final_target-exprs-elements[2]varno 2, varattno 3, vartype 23SCORE.degree0final_target-exprs-elements[3]varno 4, varattno 1, vartype 23COURSE.cno1 make_sort_input_target拿到的sort_input_target过滤掉了random列 sort_input_targetVar / FuncExpr指向列sortgrouprefssort_input_target-exprs-elements[0]varno 1, varattno 2, vartype 1043STUDENT.sname0sort_input_target-exprs-elements[1]varno 2, varattno 3, vartype 23SCORE.degree0sort_input_target-exprs-elements[2]varno 4, varattno 1, vartype 23COURSE.cno1 实例2中apply_scanjoin_target_to_paths会先挂投影节点后面的create_ordered_paths在创建顶层的排序节点为什么这里的投影节点在最上层因为有volatile函数在需要先排序在到投影节点上计算random函数 3.3 grouping_planner→apply_scanjoin_target_to_paths final_target create_pathtarget(root, root-processed_tlist);...sort_input_target make_sort_input_target(...);...grouping_target sort_input_target;...scanjoin_target grouping_target;...scanjoin_targets list_make1(scanjoin_target);...scanjoin_target_same_exprs list_length(scanjoin_targets) 1 equal(scanjoin_target-exprs, current_rel-reltarget-exprs);...// 1 确定没有SRF list_length(scanjoin_targets) 1// 2 这里make_one_rel出来的current_rel和上面make_sort_input_target计算出来的投影列一样都过滤掉了v函数剩下三列// scanjoin_target_same_exprs truescanjoin_target_same_exprs list_length(scanjoin_targets) 1 equal(scanjoin_target-exprs, current_rel-reltarget-exprs);apply_scanjoin_target_to_paths(root, current_rel, scanjoin_targets,scanjoin_targets_contain_srfs,scanjoin_target_parallel_safe,注意 scanjoin_target-exprs表示最终结果需要的targetlist。current_rel-reltarget-exprs表示当前生成path中带的targetlist。生成path的路径需要和scanjoin_target一致所以进入下面函数判断是否生成投影节点。如果相同scanjoin_target_same_exprstrue则不生成投影节点。如果不同scanjoin_target_same_exprsfalse则调用create_projection_path传入scanjoin_target生成投影节点。 在apply_scanjoin_target_to_paths中: apply_scanjoin_target_to_paths......foreach(lc, rel-pathlist){Path *subpath (Path *) lfirst(lc);if (tlist_same_exprs)// scanjoin_target-sortgrouprefs [0, 0, 1] 表示第三列是排序列// 因为现在的scanjoin_target同sort_input_target中只有三列投影列1、3和排序列参考上面sort_input_target表格。subpath-pathtarget-sortgrouprefs scanjoin_target-sortgrouprefs;else{Path *newpath;newpath (Path *) create_projection_path(root, rel, subpath,scanjoin_target);lfirst(lc) newpath;}}3.4 grouping_planner→create_ordered_paths 继续成成排序node grouping_planner...if (parse-sortClause)current_rel create_ordered_paths(root,current_rel,final_target,final_target_parallel_safe,have_postponed_srfs ? -1.0 :limit_tuples);create_ordered_paths最重要的入参就是final_target保存了全部的列信息和排序列的位置sortgrouprefs。注意前面生成path中的reltarget已经过滤了random列但这里没有过滤需要全量的信息。 final_targetVar / FuncExpr指向列sortgrouprefsfinal_target-exprs-elements[0]varno 1, varattno 2, vartype 1043STUDENT.sname0final_target-exprs-elements[1]funcid 1598, funcresulttype 701random()0final_target-exprs-elements[2]varno 2, varattno 3, vartype 23SCORE.degree0final_target-exprs-elements[3]varno 4, varattno 1, vartype 23COURSE.cno1 注意这里create_sort_path为hashjoin节点上面加了一层sort节点sort节点的pathtarget继承了hash节点的pathtarget也就是三列没有random函数列。注意这里的target是上面表格中的final_target也就是四列带random函数。加了sort节点后发现这里不相同所以开始增加投影列apply_projection_to_path。 create_ordered_pathsordered_rel fetch_upper_rel(root, UPPERREL_ORDERED, NULL);foreach(lc, input_rel-pathlist)is_sorted pathkeys_count_contained_inif (is_sorted)sorted_path input_path;elsesorted_path (Path *) create_sort_path(...)// 生成sorted_path// {type T_SortPath, pathtype T_Sort, pathtarget 三列 }if (sorted_path-pathtarget ! target)sorted_path apply_projection_to_path(root, ordered_rel, sorted_path, target);// 生成投影列// {type T_ProjectionPath, pathtype T_Result, pathtarget 四列 }最终生成PATH SELECT STUDENT.sname, random(), SCORE.degree FROM STUDENT LEFT JOIN SCORE ON STUDENT.sno SCORE.sno LEFT JOIN COURSE ON SCORE.cno COURSE.cno ORDER BY COURSE.cno;最终效果 4 实例【简单join】【排序volatile函数】【投影列中有volatile函数】 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(20, meth, 10); insert into course values(21, 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, 20, 100); insert into score values (1, 21, 89); insert into score values (2, 20, 99); insert into score values (2, 21, 90); insert into score values (3, 20, 87); insert into score values (3, 21, 20); insert into score values (4, 20, 60); insert into score values (4, 21, 70);explain verbose SELECT STUDENT.sname, random(), SCORE.degree FROM STUDENT LEFT JOIN SCORE ON STUDENT.sno SCORE.sno LEFT JOIN COURSE ON SCORE.cno COURSE.cno ORDER BY random();QUERY PLAN --------------------------------------------------------------------------------Sort (cost2.35..2.37 rows8 width17)Output: student.sname, (random()), score.degreeSort Key: (random())- Hash Right Join (cost1.09..2.23 rows8 width17)Output: student.sname, random(), score.degreeInner Unique: trueHash Cond: (score.sno student.sno)- Seq Scan on public.score (cost0.00..1.08 rows8 width12)Output: score.sno, score.cno, score.degree- Hash (cost1.04..1.04 rows4 width9)Output: student.sname, student.sno- Seq Scan on public.student (cost0.00..1.04 rows4 width9)Output: student.sname, student.sno4.1 make_one_rel结果 第一步拿到RelOptInfo current_rel query_planner(root, standard_qp_callback, qp_extra); current_rel-reltarget中忽略了random函数 { type T_PathTarget, exprs {Var{varno 1, varattno 2, vartype 1043}, // STUDENT.snameVar{varno 2, varattno 3, vartype 23} // SCORE.degree}, sortgrouprefs 0x0 }4.2 拿到final_target final_target create_pathtarget(root, root-processed_tlist); {type T_PathTarget, exprs {Var{varno 1, varattno 2, vartype 1043}, // STUDENT.snameFuncExpr {xpr {type T_FuncExpr}, funcid 1598}, // random()Var{varno 2, varattno 3, vartype 23} // SCORE.degree}, sortgrouprefs [0, 1, 0] }4.3 构造排序targetmake_sort_input_target sort_input_target make_sort_input_target(root, final_target, have_postponed_srfs); {type T_PathTarget,exprs {Var{varno 1, varattno 2, vartype 1043}, // STUDENT.snameFuncExpr {xpr {type T_FuncExpr}, funcid 1598}, // random()Var{varno 2, varattno 3, vartype 23} // SCORE.degree}, sortgrouprefs [0, 1, 0] }4.4 apply_scanjoin_target_to_paths增加投影 apply_scanjoin_target_to_paths执行后增加投影节点 { path {type T_ProjectionPath, pathtype T_Result }4.5 create_ordered_paths后增加排序节点在最顶层 { path {type T_SortPath, pathtype T_Sort }
http://www.hkea.cn/news/14329282/

相关文章:

  • 中色十二冶金建设有限公司网站扬中网站建设怎么样
  • 企业网站建设规划的基本原则有哪些电脑做网站主机
  • 个人工作室可以做哪些项目免费的关键词优化工具
  • 微网站开发的比较总结聊城市 网站制作
  • 求一个能用的网站北京手机响应式网站建设设计
  • flash做网站轮播图个人社保缴费比例
  • 租房子网站怎么做wordpress腾讯云搭建网站
  • 360未经证实的网站如何做网络营销方式有哪些各方式的优缺点有哪些
  • 建个企业网站收费拍宣传片比较好的公司
  • 图怪兽logo设计官网seo外包大型公司
  • 电子商务网站建设与管理的重要性专业网站建设是哪家便宜
  • 2017做网站怎么赚钱建网站方案
  • 北京做网站好的网站建设公司如何写网站建设报告
  • wordpress 镜像域名福州seo计费
  • 青岛如何建立企业网站企业郑州网站建设找哪家好
  • ASP网站开发教程实验总结泽州县住房保障和城乡建设局网站
  • 做效果图赚钱的网站深圳龙岗网络公司
  • 房地产 网站 设计制作惠州做网站开发
  • 刷网站关键词排名原理最新国际军事动态
  • 网站报价文档买个网站域名多少钱一年
  • 无锡做网站首选众诺wordpress缓存方案
  • 直接用源码做网站盗版吗网站做竞价经常会被攻击吗
  • 手机版景区网站网页微信二维码付款怎么弄
  • 信用网站建设内容知名的饰品行业网站开发
  • 电商扶贫网站建设陕煤建设集团铜川分公司网站
  • 图书网站建设策划书1万字网站制作的建设大纲ppt
  • 适合前端开发的电脑推荐合肥正规的seo公司
  • 西安网站建设技术外包网站公司网站开发方案
  • 网站建设宣传海报专题网站建站
  • 网站建设开发报价单报价公司