作者小头像 Lv.1
27 成长值

个人介绍

这个人很懒,什么都没有留下

感兴趣或擅长的领域

暂无数据
个人勋章
TA还没获得勋章~
成长雷达
0
27
0
0
0

个人资料

个人介绍

这个人很懒,什么都没有留下

感兴趣或擅长的领域

暂无数据

达成规则

发布时间 2020/03/31 10:24:39 最后回复 wei 2020/04/29 18:13:38 版块 社区活动
29645 114 1
他的回复:
华为云账号:s250646580 微信昵称:困第5章 DAY5 优化实战案例进阶关联更新优化案例使用merge,做嵌套循环,可以hash join,还可以并行通过PLSQL方式,根据rowid更新;如果要更新的数据非常多,最好按照rowid排序;可以控制批量提交数量;使用BULK COLLECT和FORALL更新。外连接有OR关联条件只能走NL,而且驱动表固定为主表,此时不能走HASH连接。扩展统计信息优化案例嵌套循环的内表不应该走全表扫描,根据过滤条件创建索引从而让NL被驱动表走索引。优化器一般对多个列进行Rows估算的时候通常容易算错,对连接列收集了扩展统计信息。使用LISGAGG分析函数优化WM_CONCAT,wm_concat返回的是CLOB类型,性能比较差,尽量使用Listagg代替。INSTR非等值关联优化,因为SQL中关联条件是instr,这时只能走嵌套循环,不能走HASH连接,也不能走排序合并连接,排序合并连接一般用于>=,>,,=。ROW LEVEL SECURITY优化案例:子查询中有union,不添加HINT:NO_UNNEST,将in改写为exists,这时优化器会自动走Filter,也能达到优化目的。子查询非嵌套优化对子查询添加了HINT:NO_UNNEST,让子查询不展开,从而不去干扰执行计划;如果不想添加HINT,我们可以将in改成exists,因为子查询中有固化子查询关键字,这时SQL不能展开,会自动走Filter,也能达到添加HINT:NO_UNNEST的效果,但是,这并不是说exists比in性能好。如果where子查询中没有固化子查询关键字,不管写成in还是写成exists,效率都是一样的,因为CBO始终能将子查询展(unnest)。如果where子查询中有固化子查询关键字,这时我们最好用in而不是exists,因为in可以控制子查询是否展开,而exists无法展开。滥用外连接导致无法谓词推入在进行SQL优化的时候,我们必须知道一个SQL最终应该返回多少行数据,因为知道了SQL最终返回数据,就能判断表连接究竟是采用嵌套循环还是采用HASH连接。使用CARDINALITY优化SQL可以使用HINT:CARDINALITY。/*+ cardinality(a 10000) */表示指定a表有1万行数据。/*+ cardinality(@a 10000) */表示指定queryblock a有1万行数据。或者使用动态采样,或者直接指定正确的连接方式。SQL审核规则外键没创建索引的表建议在外键列上创建索引,外键列不创建索引容易导致死锁。级联删除的时候,外键列没有索引会导致表被全表扫描。需要收集直方图的列当一个表比较大,列选择性(NDV/num_rows)低于5%,而且列出现在where条件中,为了防止优化器估算Rows出现较大偏差,我们需要对这种列收集直方图。必须创建索引的列当一个表比较大,列选择性超过20%,列出现在where条件中并且没有创建索引,我们可以对该列创建索引从而提升SQL查询性能。抓出表被多次反复调用SQL在开发过程中,我们应该避免在同一个SQL语句中对同一个表多次访问。我们可以通过下面SQL抓出同一个SQL语句中对某个表进行多次扫描的SQL。抓出走了FILTER的SQL当where子查询没能unnest,执行计划中就会出现FILTER,对于此类SQL,我们应该在上线之前对其进行改写,避免执行计划中出现FILTER。抓出返回行数较多的嵌套循环SQL两表关联返回少量数据应该走嵌套循环,如果返回大量数据,应该走HASH连接,或者是排序合并连接。如果一个SQL语句返回行数较多(大于1万行),SQL的执行计划在最后几步(Id=5)走了嵌套循环,我们可以判定该执行计划中的嵌套循环是有问题的,应该走HASH连接。抓出NL被驱动表走了全表扫描的SQL嵌套循环的被驱动表应该走索引。抓出走了TABLE ACCESS FULL的SQL如果一个大表走了全表扫描,会严重影响SQL性能。抓出走了INDEX FULL SCAN的SQLINDEX FULL SCAN会扫描索引中所有的叶子块,单块读。如果索引很大,执行计划中出现了INDEX FULL SCAN,这时SQL会出现严重的性能问题。抓出走了INDEX SKIP SCAN的SQL当执行计划中出现了INDEX SKIP SCAN,通常说明需要额外添加一个索引。抓出索引被哪些SQL引用有时开发人员可能会胡乱建立一些索引,但是这些索引在数据库中可能并不会被任何一个SQL使用。这样的索引会增加维护成本,我们可以将其删掉。抓出走了笛卡儿积的SQL当两表没有关联条件的时候就会走笛卡儿积,当Rows被估算为1的时候,也可能走笛卡儿积连接。抓出走了错误的排序合并连接的SQL排序合并连接一般用于非等值关联,如果两表是等值关联,我们建议使用HASH连接代替排序合并连接,因为HASH连接只需要将驱动表放入PGA中,而排序合并连接要么是将两个表放入PGA中,要么是将一个表放入PGA中、另外一个表走INDEXFULL SCAN,然后回表。如果两表是等值关联并且两表比较大,这时应该走HASH连接而不是排序合并连接。抓出走了低选择性索引的SQL如果一个索引选择性很低,说明列数据分布不均衡。当SQL走了数据分布不均衡列的索引,很容易走错执行计划,此时我们应该检查SQL语句中是否有其他过滤条件,如果有其他过滤条件,可以考虑建立组合索引,将选择性高的列作为引导列。抓出可以创建组合索引的SQL(回表再过滤选择性高的列)回表次数太多会严重影响SQL性能。当执行计划中发生了回表再过滤并且过滤字段的选择性比较高,我们可以将过滤字段包含在索引中避免回表再过滤,从而减少回表次数,提升查询性能。抓出可以创建组合索引的SQL(回表只访问少数字段)回表次数太多会严重影响SQL性能。当SQL走索引回表只访问表中少部分字段,我们可以将这些字段与过滤条件组合起来建立为一个组合索引,这样就能避免回表,从而提升查询性能。
发布时间 2020/03/31 10:24:39 最后回复 wei 2020/04/29 18:13:38 版块 社区活动
29645 114 1
他的回复:
 华为云账号:s250646580 微信昵称:困第4章 DAY4 优化实战案例组合索引优化案例如果A条件命中140万数据,B条件命中10万条数据,但是A和B组合条件只命中100条件数据,并且都是等值条件,那么应该创建A,B的组合索引。直方图优化案例对于嵌套循环,我们首先要检查驱动表返回的真实行数是否与估算的行数有较大偏差。对偏差列收集直方图。嵌套循环内表的索引必须包含连接列嵌套循环内表的索引一定要包含连接列,如果只有过滤条件的索引就不应该选择嵌套循环,因为内表同样的数据要被扫描很多遍,不如选择。hash join优化SQL需要注意表与表之间关系,被驱动表走索引返回数据量太多导致性能问题INDEX FAST FULL SCAN优化案例:。HINT:INDEX_FFS(表名/别名索引名),当需要从表中查询出大量数据但是只需要获取表中部分列的数据的,我们可以利用索引快速全扫描代替全表扫描来提升性能。分页语句优化案例过滤条件是等值访问,我们可以把过滤条件放在前面,排序列放在后面,内表的连接列必须有索引。ORDER BY取别名列优化案例:别名不要与列名一样半连接反向驱动主表案例:小表与大表关联,如果大表连接列基数比较高,可以走嵌套循环,让小表驱动大表,大表走连接列的索引。如果一个SQL语句中,某个表会被访问多次,而且每次访问的限制条件一样的话,就可以使用with as来提高性能。注意:如果with as 短语没有被调用2次以上,CBO就不会将with as短语获取的数据放入temp表,如果想要将数据放入temp表需要使用materialize hint连接列数据分布不均衡导致性能问题树形查询优化案例:对于树形查询,很难通过SQL改写减少start with 子查询中表被多次扫描,所以只能想办法减少表被扫描的体积。本地索引优化案例:如果过滤条件中有分区字段,一般都创建本地索引。如果过滤条件中没有分区字段,一般都创建global索引。标量子查询优化案例:标量子查询可以等价改写为外连接。
发布时间 2020/03/31 10:24:39 最后回复 wei 2020/04/29 18:13:38 版块 社区活动
29645 114 1
他的回复:
 华为云账号:s250646580 微信昵称:困第3章 DAY3 查询变换和优化技巧Oracle的Cost计算公式Cost = (#SRds* sreadtim+#MRds* mreadtim+CPUCycles/ cpuspeed/1000) / sreadtime#SRds-number of single block reads 表示单块读次数#MRds-number of multi block reads 表示多块读次数#CPUCyles-number of CPU cycles CPU时钟周期数sreadtim-single block read time 一次单块读耗时,单位:毫秒mreadtim-multi block read time 一次多块读耗时,单位:毫秒cpuspeed-CPU cycles per second CPU的主频,单位:MHzCost =(单块读耗时+多块读耗时+CPU耗时)/单块读的耗时Cost是语句的预计执行时间的总和,以单块读取时间为单位的形式来表示。SQL优化的核心思想就是想方设法减少SQL的物理I/O次数(不管是单块读次数还是多块读次数)。即使有缓存,减少块的扫描次数也可以降低CPU的占用。查询变换:子查询非嵌套当where子查询中有in、not in、exists、not exists等,CBO会尝试将子查询展开(unnest),从而消除FILTER,这个过程就叫作子查询非嵌套。子查询非嵌套的目的就是消除FILTER。当子查询语句含有exists或者not exists时,子查询中有固化子查询关键词(union/union all/start with connectby/rownum/cube/rollup),那么执行计划中就容易产生FILTER视图合并(消除)当SQL语句中有内联视图(in-line view,from后面的子查询),或者SQL语句中有用create view创建的视图,CBO会尝试将内联视图/视图拆开,进行等价的改写,这个过程就叫作视图合并。执行计划中,可以看到VIEW关键字。当视图中有固化子查询关键字的时候,就不能发生视图合并,固化子查询的关键字包括union、union all、start with connect by、rownum、cube、rollup。谓词下推当SQL语句中包含不能合并的视图,同时视图有谓词过滤(也就是where过滤条件),CBO会将谓词过滤条件推入视图中,这个过程就叫作谓词推入。执行计划的view上有*,表示该步骤有没有下推的谓词。把连接列当作谓词推入到视图中,这种谓词推入我们一般叫作连接列谓词推入。当视图中有rownum会导致无法谓词推入。当CBO选择hash join时,连接谓词也不会下推。调优技巧查看真实的基数(Rows),使用UNION代替OR。分页查询分页查询通过index full scan、组合索引、多表连接消除排序分页语句中也不能有distinct、groupby、max、min、avg、union、unionall等关键字。分页查询避免频繁统计总数。从第一页翻到最后一页如果是静态数据,建议一次性select出所有数据,数据库内部会分批fetch数据,分批取数据,建议走索引范围扫描的方式。多值查询无法用组合索引规避排序大表关联一般是使用hash join。DBLINK优化将本地表b传输到远端,在远端进行关联,然后再将结果集传回本地,这时需要使用hint:driving_siteselect /*+ driving_site(a) */ * from a@dblink, b where a.id = b.id;对表进行ROWID切片对于非分区表,我们可以对表按照ROWID切片,然后开启多个窗口同时执行SQL,这样既能加快执行速度,还能减少对UNDO的占用。内置函数DBMS_ROWID.ROWID_CREATE()用于生成ROWID。
发布时间 2020/03/31 10:24:39 最后回复 wei 2020/04/29 18:13:38 版块 社区活动
29645 114 1
他的回复:
 华为云账号:s250646580 微信昵称:困第2章 DAY2 优化多表连接嵌套循环嵌套循环的算法驱动表返回一行数据,通过连接列传值给被驱动表,驱动表返回多少行,被驱动表就要被扫描多少次。在执行计划中,离NESTED LOOPS关键字最近的表就是驱动表。驱动表应该返回少量数据,关联条件的索引命中的数据必须很少。嵌套循环被驱动表必须走索引。嵌套循环被驱动表走索引只能走INDEXUNIQUE SCAN或者INDEX RANGE SCAN。use_nl(d,e)表示让两表走嵌套循环,大表过滤之后返回的数据量很少就可以当NL驱动表。判断两表关联是否应该走NL应该直接查看两表关联之后返回的数据量,如果两表关联之后返回的数据量少,可以走NL;返回的数据量多,应该走HASH连接。嵌套循环不需要消耗PGA。HASH连接哈希连接只支持等值连接,返回大量数据,将较小的表选为驱动表,数据完全读入PGA中的work area,PGA不能完全容纳驱动表时,驱动表就会溢出到临时表空间,进而产生磁盘HASH连接,这时候HASH连接性能会严重下降。尽量将需要的列放在select list中,可以减少驱动表对PGA的占用。排序合并连接(SORT MERGEJOIN)排序合并连接主要用于处理两表非等值关联,比如>,>=,,=,,但是不能用于instr、substr、like、regexp_like关联,instr、substr、like、regexp_like关联只能走嵌套循环。笛卡儿连接(CARTESIAN JOIN)两个表关联没有连接条件的时候会产生笛卡儿积,这种表连接方式就叫笛卡儿连接。执行计划中MERGE JOIN CARTESIAN就表示笛卡儿连接。在多表关联的时候,两个表没有直接关联条件,但是优化器错误地把某个表返回的Rows算为1行(注意必须是1行),这个时候也可能发生笛卡儿连接。标量子查询(SCALARSUBQUERY)当一个子查询介于select与from之间,这种子查询就叫标量子查询。标量子查询类似一个天然的嵌套循环,而且驱动表固定为主表。标量子查询中子查询的表连接列也必须包含在索引中。尽量避免使用标量子查询。半连接(SEMI JOIN)两表关联只返回一个表的数据就叫半连接。半连接一般就是指的in和exists。in和exists一般情况下都可以进行等价改写。以子查询为驱动,对主表嵌套循环,适用于子查询的数据集非常小并且主表有索引的场景。以主表为驱动表,对子查询嵌套循环 ,适用于主表数据集较少,子查询连接条件有索引的场景以主表为Hash表做hash连接,适用于两表连接结果集比较大,主表较小的场景以子表为Hash表做hash连接 ,适用于两表连接结果集比较大,子表较小的场景反连接(ANTI JOIN)两表关联只返回主表的数据,而且只返回主表与子表没关联上的数据,这种连接就叫反连接。反连接一般就是指的not in和not exists。not in和not exists的区别not in的话,只要子查询中有一个null,结果就为空,而notexists不会,说明not in认为null是未知的,可以等于任意数。如果反连接采用not in写法,我们需要在where条件中剔除null。子查询无法展开就是优化器将嵌套的子查询展开成一个等价的join,然后去优化这个join。子查询不能展开,执行计划一般会显示为filter,类似嵌套循环,固定以主表为驱动表。PG的执行计划 嵌套循环/Hash join/Hash semi join解读
发布时间 2020/03/31 10:24:39 最后回复 wei 2020/04/29 18:13:38 版块 社区活动
29645 114 1
他的回复:
华为云账号:s250646580  微信昵称:困第一章 SQL优化基础谓词就是返回值为真值的函数。card:结果集数量。NDV:基数,列的唯一数量。Selectivity 命中率,一般命中5%以内的数据走索引,超过5%的数据使用全表扫描。列没有创建索引并且选择性大于20%,该列就必须创建索引,从而提升SQL 查询性能cost:SQL执行代价直方图:是用来帮助CBO在对NDV很低、数据分布不均衡的列进行Rows估算的时候,可以得到更精确的Rows 。当列出现在where条件中,列的选择性小于1%并且该列没有收集过直方图,这样的列就应该收集直方图。针对包含很少不同值的数据集,生成频率直方图;另一种是针对包含很多不同的数据集,生成高度均衡直方图。当NDV小于桶数时(直方图的桶数有限,一般为256个),为频率直方图,否则为高度直方图。回表:当对一个列创建索引之后,索引会包含该列的键值以及键值对应行所在的rowid。通过索引中记录的rowid访问表中的数据就叫回表。如果只访问索引列或者使用组合索引可以避免回表。sqlplus 参数arraysize表示服务器每次传输多少行数据到客户端,默认15,修改解决逻辑读放大问题。show arraysize;set arraysize 5000;聚集因子:表示一个索引对应数据在表中的顺序性,它的大小介于表的块数和表行数之间,影响回表。聚集因子只会影响索引范围扫描(INDEXRANGE SCAN)以及索引全扫描(INDEX FULLSCAN),因为只有这两种索引扫描方式会有大量数据回表。降低聚集因子的影响:1)重建表,按照某个索引列的顺序2)通过组合索引避免回表3)使用Oracle的clustertable4)增大buffercache将大部分数据缓存到内存或者使用内存表统计信息:是为了让优化器选择最佳执行计划,以最少的代价(成本)查询出表中的数据。统计信息主要分为表的统计信息、列的统计信息、索引的统计信息、系统的统计信息、数据字典的统计信息以及动态性能视图基表的统计信息。表的统计信息主要包含表的总行数(num_rows)、表的块数(blocks)以及行平均长度(avg_row_len)。列的统计信息主要包含列的NDV、列中的空值数量以及列的数据分布情况(直方图)。索引的统计信息主要包含索引blevel(索引高度-1)、叶子块的个数(leaf_blocks)以及聚集因子(clustering_factor)。如果累计增删改的数量超过一定的比例(一般为10%),统计信息状态变为陈旧。dba_tab_statistics.stale_stats查询,YES表示过期。如果一个表从来没收集过统计信息,默认情况下Oracle会对表进行动态采样(Level=2)以便优化器估算出较为准确的Rows执行计划中dynamic sampling used for this statement(level=2)表示启用了动态采样Oracle动态采样的级别分为11级当系统中有全局临时表,就需要使用动态采样,因为全局临时表无法收集统计信息,我们建议对全局临时表至少启用level 4进行采样。当执行计划中表的Rows估算有严重偏差的时候,建议对全局临时表至少启用level 4进行采样。在数据仓库系统中sql拼接过长,过滤条件太复杂,从而导致优化器不能估算出较为准确的Rows而产生了错误的执行计划,我们可以考虑启用动态采样level 6观察性能是否有所改善。如果某个表需要启用动态采样,直接在SQL语句中添加HINT即可。获取执行计划:Autotraceset autoton:该命令会运行SQL并且显示运行结果,执行计划和统计信息。set autottrace:该命令会运行SQL,但不显示运行结果,会显示执行计划和统计信息。set autottrace exp:运行该命令查询语句不执行,DML语句会执行,只显示执行计划。set autottrace stat:该命令会运行SQL,只显示统计信息。set autotoff:关闭AUTOTRACE。explain planexplain plan for SQL语句;select * from table(dbms_xplan.display);select * from table(dbms_xplan.display(NULL, NULL, 'advanced -projection'));高级执行计划比普通执行计划多了Query BlockName/Object Alias和OutlineData。查看带有A-TIME的执行计划alter session set statistics_level=all;或者在SQL语句中添加hint:/*+ gather_plan_statistics*/select * from table(dbms_xplan.display_cursor(null,null,'allstatslast'));谓词过滤谓词(filter):过滤条件,不影响访问路径,只起过滤作用访问谓词(access):索引扫描条件,影响访问路径TABLE ACCESS BY INDEX ROWID前面有“*”号,表示回表再过滤。回表再过滤说明数据没有在索引中过滤干净。当TABLE ACCESS BYINDEX ROWID前面有“*”号时,可以将“*”号下面的过滤条件包含在索引中,这样可以减少回表次数,提升查询性能。访问路径访问路径指的就是通过哪种扫描方式获取数据。TABLE ACCESS FULL/TABLE ACCESS BY USER ROWID/TABLE ACCESS BY ROWID RANGE/TABLE ACCESS BY INDEX ROWID(回表)/INDEX UNIQUE SCAN/INDEX RANGE SCAN/INDEX RANGE SCAN DECENDING/INDEX FULL SCAN/INDEX FAST FULL SCAN/INDEX FULL SCAN(MIN/MAX)/INDEX SKIP SCAN走索引返回的数据越多,需要耗费的I/O次数也就越多,因此,返回大量数据应该走全表扫描或者是INDEX FAST FULLSCAN,返回少量数据才走索引扫描。根据上述理论,我们一般建议返回表中总行数5%以内的数据,走索引扫描,超过5%走全表扫描。PG执行计划解读:参数与节点含义解释
发布时间 2020/03/31 10:20:45 最后回复 wei 2020/04/29 16:02:00 版块 社区活动
23790 78 0
他的回复:
结业实践任务1      1)查询员工名字(ENAME)=‘XXX’的DEPTNO,区分大小写,不希望回表。需提供执行成功截图。   优化方式:为员工名字(ENAME)添加索引,访问路径为INDEX UNIQUE SCAN。   sql:   CREATE INDEX on emp(ename);   ANALYZE emp;   SELECT empno FROM emp where ename='8191c14306';执行结果:2)查询每个部门(DEPTNO)的人数。需提供执行成功截图。    优化方式:走hash连接,访问路径表dept索引全扫描,emp全表扫描。。    sql:   select dept.deptno,count(1) from dept,emp where dept.deptno =emp.deptno GROUP BY dept.deptno ;执行结果:3)查询DEPTNO =1并且HIREDATE最大的10个员工。需提供执行成功截图。   优化方式:DEPTNO建立索引,不用回表。访问路径为索引范围扫描。select ename,hiredate  from emp where deptno=1 ORDER BY emp.hiredate desc LIMIT 10;执行结果:4)下面这个SQL有什么问题?如何优化?  问题:字符型字段为数字时在where条件里没添加引号,导致索引被抑制,走了全表扫描,  优化方式:字符型字段添加引号。  sql:select * from emp where job = '10';  执行结果: 结业实践任务21)查询工资范围在1000~1010的员工部门分布情况。优化方式:在emp_salary表sal列建立索引走索引范围扫描sql:select dept.dname,COUNT(1) from dept,emp,emp_salarywhere dept.deptno=emp.deptnoand emp.empno=emp_salary.empnoand (emp_salary.sal  between 1000 and 1010) group by dept.dname;2)查询哪些员工的部门在dept中不存在,分别使用外连接和not exists实现。外连接:select emp.ename,emp.deptno from emp LEFT JOIN  dept on emp.deptno=dept.deptno where dept.deptno is null;not exists:select emp.ename,emp.deptno from emp where not EXISTS(select 1 from dept where emp.deptno=dept.deptno);外连接:not exists:结业实践任务31)分页查询:查询Top 10的emp表的数据,要求按照工资降序。优化方式:显示的时候只有emp表的数据,去掉emp_salary表的排序字段,把过滤条件放在前面,排序列放在后面sql:select * from (select a.* from emp a inner join emp_salary b on a.empno=b.empno where 1=1  order by b.sal desc)where rownum= 10;2)下面这个SQL应该如何提升性能:优化方式:使用merge,可以以emp_salary为驱动表做嵌套循环,可以hash join,还可以并行sql: merge into emp a using (select b.sal,b.empno from emp_salary b where b.sal between 1000 and 1050) c on (a.empno = c.empno)  when matched then update set a.remark=c.sal;