当前位置:文档之家› 《数据库性能优化》-PPT课件

《数据库性能优化》-PPT课件

数据库性能优化
B2B-DBA-陈立-2019年Q3
主题




基本元素 访问堆表 访问B树索引 案例分析 执行计划
基本元素-总览


一本字典---------------一个表 字典中的一页----------一个数据块 一个字的解释----------一笔记录 页码跟行号------------ROWID
基本元素-堆表

物理上由若干数据块组成

物理上的分界线:High Water Mark
每笔数据的唯一地址:ROWID

逻辑上由若干数据行组成

基本元素-数据块


保存数据的最小容器 读取数据的最小单位(8k或16k,固定大小)
基本元素-ROWID


访问一笔记录的最快方式 ROWID只是一个坑,不是一个萝卜,用它来 访问数据虽然快,但是不安全。因为随着 DELETE/INSERT操作,坑里埋的萝卜会变。 坑还是原来的坑,萝卜已经不是原来的萝卜了。
访问堆表-STOP机制

查询到指定的记录数之后就停止扫描

无需借助索引,也不必访问整张表的所有数据块

在字典中找出5个笔画数为20的字
访问B树索引-典型结构
访问B树索引-特点




自索引的索引 平衡树-----每个叶节点到根节点的距离相等 叶节点之间存在有序链表结构 对 =, >, <, >=, <=, like ‘a%’ 等操作效率 极高 对 <>, like ‘%a%’, like ‘%a’ 操作效率差
实际问题-7

问:这个SQL如何优化?
SELECT * FROM (SELECT t.*, rownum AS rn FROM (SELECT * FROM ._article WHERE domain_id = :1 AND draft = 0 ORDER BY domain_id, draft, gmt_create DESC) t WHERE rownum <= :2) WHERE a.rn >= :3
实际问题-1
问:在索引字段上施加函数,为什么性能差 to_char(gmt_create,’ mmdd’) =‘0101’

答:因为无法使用索引 正确的写法: gmt_create between to_date('20090101','yyyymmdd') and to_date('20090102','yyyymmdd') 用索引范围扫描


答:用了索引快速全扫描 或者 其他低效的扫描 方式。 正确的做法:创建以group_id为首列的索引,使 用索引范围扫描。
实际问题-4

问:计数为什么有时候count(id)比count(*) 慢?
答:count(id)等价于 count(*) where id is not null,如果没有(id)索 引,那么会用全表扫描,而count(*)会自动选择 最优的索引用索引快速全扫描。 正确的写法:计数统一使用count(*)。
实际问题-7

答:在索引内完成过滤/排序/分页,取得一页 的ROWID,用它们再去跟原表做join。
SELECT t.* FROM (SELECT rid, rownum AS rn FROM (SELECT ROWID AS rid FROM ._article WHERE domain_id = :1 AND draft = 0 ORDER BY domain_id, draft, gmt_create DESC) WHERE rownum <= :2) a, ._article t WHERE a.rn >= :3 AND a.rid = t.ROWID
访问B树索引-索引唯一扫描
访问B树索引-索引范围扫描Βιβλιοθήκη 访问B树索引-索引快速全扫描
Select count(*) from table1
访问B树索引-代价



索引唯一扫描:o(1)------索引的层次数 索引范围扫描:o(n)------所需要返回的叶块 索引快速全扫描:o(N)----所有叶块
实际问题-6

问:索引(member_id, subject)这两句性能 有差别吗?



(A): select subject from offer where member_id=#member_id#; (B): select subject, gmt_create from offer where member_id=#member_id#; 答:两句都用了索引范围扫描,(B)还需要根据 索引中查到的ROWID访问表里的记录,当对应 的记录数较多时,比(A)的性能差很多。

实际问题-2

问:在索引字段上用全模糊,为什么性能差 member_id like ‘%alibaba%’

答:因为无法使用索引。 正确的做法:B树索引无法解决这种需求。考虑 用其他技术手段代替,比如搜索引擎。
实际问题-3

问:索引是 (member_id, group_id), 为什 么这个性能差 where group_id=89721

实际问题-5

判断member_id在offer表中是否存在记录, 哪个写法性能好?



(A): select count(*) from offer where member_id=#member_id#; (B): select count(*) from offer where member_id=#member_id# and rownum<=1; 两种写法都用了索引范围扫描,(B)在这个基础 上还用到了STOP机制,查到第一笔记录之后就 立刻停止了扫描,所以性能更好。
执行计划-提出问题
执行计划-设计思路

算法一:

遍历新华字典,对其中的每个字都去语文课本里 找对应的字,每个字的查找都是将整本课本遍历 一遍。直到将课本中该课的生字全部找到。
访问堆表-全表扫描

全表扫描


用多快读的方式访问高水位线以下的所有数据块 哪怕这些数据块里现在都没有数据 哪怕最终只得到少量的记录

就像在一本没有索引的字典里找出所有单人旁 的字,你必须将整本字典从头到尾查阅一遍。
访问堆表-ROWID访问

访问指定ROWID的记录

最快的访问方式

查看字典中第X页第Y行的字
相关主题