• SQL优化策略(数据仓库)


    根据数据库知识,我们可以列出每种硬件主要的工作内容:
    CPU及内存:缓存数据访问、比较、排序、事务检测、SQL解析、函数或逻辑运算;
    网络:结果数据传输、SQL请求、远程数据库访问(dblink);
    硬盘:数据访问、数据写入、日志记录、大数据量排序、大表连接。
    根据当前计算机硬件的基本性能指标及其在数据库中主要操作内容,可以整理出如下图所示的性能基本优化法则:

    这个优化法则归纳为5个层次:
    1、 减少数据访问(减少磁盘访问)
    2、 返回更少数据(减少网络传输或磁盘访问)
    3、 减少交互次数(减少网络传输)
    4、 减少服务器CPU开销(减少CPU及内存开销)
    5、 利用更多资源(增加资源)

    数据库访问优化法则详解

    1、减少数据访问

    1.1、创建并使用正确的索引

    1.1.1、索引分类:

    常见的索引有:B-TREE索引、位图索引、全文索引,位图索引一般用于数据仓库应用,全文索引由于使用较少,这里不深入介绍。B-TREE索引包括很多扩展类型,如组合索引、反向索引、函数索引等等,以下是B-TREE索引的简单介绍:

    B-TREE索引也称为平衡树索引(Balance Tree),它是一种按字段排好序的树形目录结构,主要用于提升查询性能和唯一约束支持。B-TREE索引的内容包括根节点、分支节点、叶子节点。

    叶子节点内容:索引字段内容+表记录ROWID

    根节点,分支节点内容:当一个数据块中不能放下所有索引字段数据时,就会形成树形的根节点或分支节点,根节点与分支节点保存了索引树的顺序及各层级间的引用关系。

    1.1.2、SQL使用索引情况:

    INDEX_COLUMN = ?
    INDEX_COLUMN > ?
    INDEX_COLUMN >= ?
    INDEX_COLUMN < ?
    INDEX_COLUMN <= ?
    INDEX_COLUMN between ? and ?
    INDEX_COLUMN in (?,?,...,?)
    INDEX_COLUMN like '?%'(后导模糊查询)
    T1. INDEX_COLUMN=T2. COLUMN1(两个表通过索引字段关联)

    1.1.3、SQL不使用索引情况:

    INDEX_COLUMN <> ?
    INDEX_COLUMN not in (?,?,...,?)
    function(INDEX_COLUMN) = ?(经过普通运算或函数运算后的索引字段不能使用索引)
    INDEX_COLUMN + 1 = ?
    INDEX_COLUMN || 'a' = ?
    INDEX_COLUMN like '%'||?(含前导模糊查询的Like语法不能使用索引)
    INDEX_COLUMN like '%'||?||'%'
    INDEX_COLUMN is null(B-TREE索引里不保存字段为NULL值记录,因此IS NULL不能使用索引)
    NUMBER_INDEX_COLUMN='12345'
    CHAR_INDEX_COLUMN=12345(Oracle在做数值比较时需要将两边的数据转换成同一种数据类型,如果两边数据类型不同时会对字段值隐式转换,相当于加了一层函数处理,所以不能使用索引)
    a.INDEX_COLUMN=a.COLUMN_1(给索引查询的值应是已知数据,不能是未知字段值)

    经过函数运算字段的字段要使用可以使用函数索引。
    有时候我们会使用多个字段的组合索引,如果查询条件中第一个字段不能使用索引,那整个查询也不能使用索引,
    Oracle9i后引入了一种index skip scan的索引方式来解决类似的问题,但是通过index skip scan提高性能的条件比较特殊,使用不好反而性能会更差。

    1.1.4、查看SQL是否使用了正确的索引:

    简单SQL可以根据索引使用语法规则判断,复杂的SQL不好办,判断SQL的响应时间是一种策略,但是这会受到数据量、主机负载及缓存等因素的影响,有时数据全在缓存里,可能全表访问的时间比索引访问时间还少。要准确知道索引是否正确使用,需要到数据库中查看SQL真实的执行计划。

    1.2、只通过索引访问数据

    有些时候,我们只是访问表中的几个字段,并且字段内容较少,我们可以为这几个字段单独建立一个组合索引,这样就可以直接只通过访问索引就能得到数据,一般索引占用的磁盘空间比表小很多,所以这种方式可以大大减少磁盘IO开销。

    如:select id,name from company where type='2';
    如果这个SQL经常使用,我们可以在type,id,name上创建组合索引
    create index my_comb_index on company(type,id,name);
    有了这个组合索引后,SQL就可以直接通过my_comb_index索引返回数据,不需要访问company表。

    1.3、优化执行计划

    2、返回更少的数据

    OLAP系统没什么优化空间

    3、减少交互次数

    OLAP系统没什么优化空间

    4、减少数据库服务器CPU运算

    4.1、使用绑定变量

    数据仓库应用,这种应用一般并发不高,但是每个SQL执行时间很长,SQL解析的时间相比SQL执行时间比较小,绑定变量对性能提高不明显。数据仓库一般都是内部分析应用,所以也不太会发生SQL注入的安全问题。

    4.2、合理使用排序

    Oracle的排序算法一直在优化,但是总体时间复杂度约等于nLog(n)。普通OLTP系统排序操作一般都是在内存里进行的,对于数据库来说是一种CPU的消耗,曾在PC机做过测试,单核普通CPU在1秒钟可以完成100万条记录的全内存排序操作,所以说由于现在CPU的性能增强,对于普通的几十条或上百条记录排序对系统的影响也不会很大。但是当你的记录集增加到上万条以上时,你需要注意是否一定要这么做了,大记录集排序不仅增加了CPU开销,而且可能会由于内存不足发生硬盘排序的现象,当发生硬盘排序时性能会急剧下降,这种需求需要与DBA沟通再决定,取决于你的需求和数据,所以只有你自己最清楚,而不要被别人说排序很慢就吓倒。

    以下列出了可能会发生排序操作的SQL语法:
    Order by
    Group by
    Distinct
    Exists子查询
    Not Exists子查询
    In子查询
    Not In子查询
    Union(并集),Union All也是一种并集操作,但是不会发生排序,如果你确认两个数据集不需要执行去除重复数据操作,那请使用Union All 代替Union。
    Minus(差集)
    Intersect(交集)
    Create Index
    Merge Join,这是一种两个表连接的内部算法,执行时会把两个表先排序好再连接,应用于两个大表连接的操作。如果你的两个表连接的条件都是等值运算,那可以采用Hash Join来提高性能,因为Hash Join使用Hash 运算来代替排序的操作。

    4.3、减少比较操作

    我们SQL的业务逻辑经常会包含一些比较操作,如a=b,a<b之类的操作,对于这些比较操作数据库都体现得很好,但是如果有以下操作,我们需要保持警惕:
    Like模糊查询,如下所示:
    a like ‘%abc%’
    Like模糊查询对于数据库来说不是很擅长,特别是你需要模糊检查的记录有上万条以上时,性能比较糟糕,这种情况一般可以采用专用Search或者采用全文索引方案来提高性能。
    不能使用索引定位的大量In List,如下所示:
    a in (:1,:2,:3,…,:n) ----n>20
    如果这里的a字段不能通过索引比较,那数据库会将字段与in里面的每个值都进行比较运算,如果记录数有上万以上,会明显感觉到SQL的CPU开销加大,这个情况有两种解决方式:
    a、 将in列表里面的数据放入一张中间小表,采用两个表Hash Join关联的方式处理;
    b、 采用str2varList方法将字段串列表转换一个临时表处理,关于str2varList方法可以在网上直接查询,这里不详细介绍。
    以上两种解决方案都需要与中间表Hash Join的方式才能提高性能,如果采用了Nested Loop的连接方式性能会更差。

    5、利用更多的资源

    年薪百万的DBA传授经验“小表走索引,大表走并行”,切记。

  • 相关阅读:
    很久没有写代码日记了。
    Bundle数据类型
    8-18 缓存垃圾清理
    关于 printf
    强制类型转换/隐式类型转换
    JAVA文件扫描(递归)
    字符串
    8-17 安卓内存清理
    【11-29】excel reader
    orale 乱码
  • 原文地址:https://www.cnblogs.com/dongchao3312/p/12780723.html
Copyright © 2020-2023  润新知