• SQL应用中级指南 Part3:(SQL的流化、高效、数据库性能的提高与调整)


    (一)对 SQL 语句优化以提高其性能

    对 SQL 语句的流化是在设计和调试数据库时影响其应用性能的重要部分。不管数据库规划的如何合理或数据设计考虑的如何健全,你都不会对你的查询返回数据的及时性感到满意,即便是错误也是如此,那么你的客户呢?如果你不遵循一些基本的指导方针那么你的客户也不会感到满意,所以你的领导对你也不会满意。
    目标:
    1. 明白 SQL 语句流的概念
    2. 明白批装入和事务过程的区别以及它们对数据库性能的影响
    3. 能够对查询的条件进行操作纵以加快数据获得
    4. 熟悉一些影响数据库调试阶段和整个过程的性能底层元素

    这里有一个类似的比喻可以帮助你明白 SQL 语句流的含义:

           游泳运动员必须在尽可能短的时间之内完成项目否则他就有可能被淘汰,那么这些游泳者必须具有足够的技术并且发挥他全部的身体的固定能力以使得他们可以以鱼一样的速度在水中运行。而且在他的每一次划水和呼吸时都必须如此,游泳者需要在每一时刻都保持他身体的流线型以减少水的阻力。

    你的SQL 查询也与此相似:

           你应该总是准确地知道你的目标是什么并尽可能地用最快的方法来实现这一目标。你要将大部分时间花在计划上少部分时间花在稍后对它的调整上。你的目标应该总是获得正确的数据和用尽可能少的时间,最终用户等待一个缓慢查询的感觉就像一个饥肠辘辘的人等一份久候不至的大餐一样,虽然你可以将大多数的查询用几种方法来输写但对查询中元素的安排的不同导致的最终时间差异可能有几秒几分钟甚至是几个小时!SQL 语句的流化过程可以找到在你的查询中排列这些元素的最优结
    果,除了流化你的 SQL 语句以外你还应该考虑到一些其他的影响你的数据库性能的因素,例如在数据库中的并发事务控制,表的索引以及对数据库的深层调试等等。

    让你的 SQL 语句更易读
    尽管实际上易读性不会影响 SQL 语句的性能,好的程序员会习惯于调用易读的代码,当你在 WHERE 子句中存在多个条件的时候尤为重要。任何人读到这个子句的时候都可以确切地知道表是否已经被正确地归并了并且也可以确切地知道条件的次序。

    -- 试着读下边的语句
    SELECT EMPLOYEE_TBL.EMPLOYEE_ID, EMPLOYEE_TBL.NAME,EMPLOYEE_PAY_TBL.SALARY, 
    EMPLOYEE_PAY_TBL.HIRE_DATE FROM EMPLOYEE_TBL, EMPLOYEE_PAY_TBL 
    WHERE EMPLOYEE_TBL.EMPLOYEE_ID=EMPLOYEE_PAY_TBL.EMPLOYEE_ID
    AND EMPLOYEE_PAY_TBL.SALARY>30000 OR (EMPLOYEE_PAY_TBL.SALARY
    BETWEEN 25000 AND 30000 AND EMPLOYEE_PAY_TBL.HIRE_DATE < SYSDATE - 365)
     
    -- 下边是相同的查询的更易读的写法
    SELECT E.EMPLOYEE_ID, E.NAME, P.SALARY, P.HIRE_DATE
    FROM EMPLOYEE_TBL E,EMPLOYEE_PAY_TBL P
    WHERE E.EMPLOYEE_ID = P.EMPLOYEE_ID AND P.SALARY > 30000
    OR (P.SALARY BETWEEN 25000 AND 30000 AND P.HIRE_DATE < SYSDATE - 365);
     
    -- 上边的查询中使用了表的别名,重要的是使用别句以后查询变得更有组织和易读性
    -- 这两个查询是一样的,但是第二个显然是更易读的
    -- 它非常具有结构性那就是查询的各个成份被回车和回车合理地分开了
    -- 你可以很容易地找到哪里是查询的 SELECT 部分(在 SELECT 子句中)
    -- 有哪些表被访问(在 FROM 子句中),哪些是需要指定的条件(在WHERE 子句中)

    全表扫描
    当数据库服务为执行某一个 SQL 语句需要对表中的每一个记录进行检查时就会发生全表扫描。它通常在执行 SELECT 语句时发生但有时也会在更新和删除记录时发生。

    全表扫描通常是因为在 WHERE 子句中使用了索引中没有的字段时发生,它就像对一本书一页一页地来看以找到所需内容一样。在大多数情况下我们使用索引,通常通过对经常在 WHERE 子句中使用的字段建立索引来避免全表扫描。索引所提供的找数据的方法与通过目录找书中的指定内容方法一样,使用索引可以提高数据的访问速度。尽管程序员们并不赞成使用全表扫描,但是有时使用它也是适当的。

    例如:

    你选择了一个表中的大多数行的时候、你在对表中的每一行记录进行更新的时候、表非常小的时候。对于头两种情况索引的效率是非常低的,因为数据库服务程序不得不频繁地读表和索引内容,也就是说索引只有在你所要找的数据只在表中所占比率很小的时候才会非常地有效,通常不会超过表中全部数据量的10%到15%,此外最好在大型表中使用索引。当你设计表和索引的时候你要考虑表的大小,合适的索引应该是建立在对数据的熟悉上,知道那一列数据是最经常引用的,如果想让索引工作得好,你需要做一些试验。

    加入一个新的索引
    你经常会发现一些SQL 语句运行的时间长得不合情理,尽管其它的语句运行的性能看起来是可以接受的,例如当数据的检索条件改变或表的结构改变以后我们会发现速度的下降,对于这种情况你首先要检查的是所用的目标表是否存在索引,大多数情况下我们会发现表是有索引的,但是在 WHERE 子句中所使用的新条件没有索引,看一下 SQL 语句中的 WHERE 子句,我们要问的是是否可以加入其它的索引?

    如果是在下列条件下那么答案是肯定的:
    最大的限制条件返回表的数据库小于表总数据量的 10%
    最大的限制条件在 SQL 语句中是经常使用的
    条件列的索相将会返回一个唯一的值
    列经常被 ORDER BY 或GROUP BY 子句所引用

    使用复合索引

    复合索引是基于表中两个或更多列的索引,如果在 SQL 语句中经常将两列一起使用时这种索引会比单列索引更有效,如果在一起的索引列经常是分开使用的,特别是在其它的查询中,那么单列索引则是更合适的。所以你要经过试验来判断在你的数据库中使用哪一种索引会是更合适的。

    在查询中各个元素的布局
    在你的查询中,WHERE 子句是根据解释器处理 SQL 语句的步骤和次序而定的。在条件中安排被索引过的列,这样的条件将会查找最少的记录,你不一定非要在WHERE 子句中使用已经被索引过的列,但是显然这样做会更有效。

    试着调整 SQL 语句以使它返回的记录数最少,在一个表中返回记录数最少的条件就是最大的限制条件。在通常的语句中你应该把最大的条件限制语句放在WHERE 子句的最后(也就是最右边)。当优化器首先读到最大条件限制语句以后它就将为以后的条件所提供的结果集缩减至最小了,下一个条件将不再搜索整个表而是搜索经过最大条件限制过的子集,所以数据的返回就会更快。

    下边的测试是我们对用两种不同的方法来查询相同的内容所耗用时间的差异:

    -- 测试一
    SET TIMING ON
    SELECT COUNT(*) FROM FACT_TABLE
    WHERE CALC_YTD = '-2109490.8'
    AND DT_STMP = '01-SEP-96'
    AND OUTPUT_CD = '001'
    AND ACTIVITY_CD = 'IN'
    AND STATUS_CD = 'A'
    AND FUNCTION_CD = '060'; // Elapsed: 00:00:15.37
     
    -- 测试二
    SET TIMING ON
    SELECT COUNT(*) FROM FACT_TABLE
    WHERE FUNCTION_CD = '060'
    AND STATUS_CD = 'A'
    AND ACTIVITY_CD = 'IN'
    AND OUTPUT_CD = '001'
    AND DT_STMP = '01-SEP-96'
    AND CALC_YTD = '-2109490.8'; // Elapsed: 00:00:01.80
     
    -- 要简单地改变所给出的统计的次序,第二个查询比第一个查询快了14 秒
    -- 那么可以设想一下当查询的结构设计不好的时候耗用几个小时的情形

    使用存储过程
    如果所使用的查询有规律可循,那么你可以试着使用过程,过程可以调用很大的一组 SQL 的语句。过程是被数据库的引擎编译后运行的,与 SQL 语句不同,数据库引擎在执行过程的时候不需要进行优化,过程相对于独立的多个SQL 语句它对于用户来说更容易使用而对于数据库来说更为有效。

    避免使用OR
    如果可能的话应该在查询中尽量避免使用逻辑操作符 OR, OR 会不可避免的根据表的大小降低查询的速度。我们发现 IN 通常比OR 要快,当然优化器的文档中并不是这样说的。

    -- 下边的例子中使用了多个 OR
    SELECT * FROM FACT_TABLE
    WHERE STATUS_CD = 'A' OR STATUS_CD = 'B' OR STATUS_CD = 'C' OR STATUS_CD = 'D'
    OR STATUS_CD = 'E' OR STATUS_CD = 'F'
    ORDER BY STATUS_CD;
     
    -- 下边是使用 IN 写成的相同的查询
    SELECT * FROM FACT_TABLE WHERE STATUS_CD IN ('A','B','C','D','E','F') ORDER BY STATUS_CD;
     
    -- 你可以自己进行一些类似的测试,你会发现你经常可以得到你自己的结论,特别是在性能方面
    -- 下边是使用子串和 IN 的又一个例子,注意第一个查询结合使用了 LIKE 和 OR
    SELECT * FROM FACT_TABLE
    WHERE PROD_CD LIKE 'AB%' OR PROD_CD LIKE 'AC%' OR PROD_CD LIKE 'BB%' OR PROD_CD LIKE 'BC%'
    OR PROD_CD LIKE 'CC%' 
    ORDER BY PROD_CD;
     
    SELECT * FROM FACT_TABLE WHERE SUBSTR(PROD_CD,1,2) IN ('AB','AC','BB','BC','CC') ORDER BY PROD_CD;
    -- 第二个例子不仅避免的使用 OR, 而且也避免了使用 LIKE 与 OR 的联合操作
    -- 你可以试一下这个例子,你会看到对于你的数据它们在实际运行时性能上的不同

    OLAP 与OLTP 的比较
    当你在调试一个数据库的时候你首先要决定的是它应该经常由谁来使用?在线的分析处理OLAP 的数据库是一个对最终用户的查询进行统计和汇总的系统,在这种环境
    下返回的数据经常用与统计报告给决策管理过程提供帮助。而在线事务过程OLTP 的数据库则是一个将主要的功能提供给最终用户输入服务的环境的系统,包括用户日复一日的查询。OLTP 系统经常用在以日为基本单位在数据库中操作数据的使用场合。数据仓库与DSS 可以从在线的事务处理数据库中得到它们所需的数据有时也可以从其它的OLAP数据库中得到数据。


    OLTP 的调试
    一个事务处理数据库是一个精密的系统,它的访问任务是由繁重的按日而定的大量的事务与查询组成,但是OLTP 通常不需要巨大的分类区域,至少它的需要没有OLAP 的那么大。大多数OLTP 的反应很迅速,但是不会进行分类。在事务处理数据库中最明显的例子就是ROLLBACK 语句需要撤消的内容的量与尺寸是与当前有多少用户在访问数据库相关的。与在每一个事务中进行的工作一样最好的办法是在一个事务处理的环境中有多个ROLLBACK命令。
    在事务处理环境中另一个涉及的问题是事务历史记录的完整性。它在每一个事务结束后都会写出,LOGS 是为恢复的目的而存在的,所以每一种SQL 解释器都需要有一种方法来对LOGS 进行备份以用于恢复点。SQL SERVER 使用的是DUMP DEVICE, ORACLE 则使用一种被称为ARCHIVELOG 模式,数据库事务记录也会涉及到性能,因为对记录的备份是额外的负荷。

    OLAP 的调试
    如果要调试OLAP 系统,例如数据仓库或决定支持的系统与调试OLTP 系统有着相当大的不同。一般说来它需要较大的空间用以进行分类,由于这种系统的目的是获得有用的用以决策的数据,所以你可以想象得到它有着相当多的复合查询,并且通常要涉及到对数据的分组和排序与事务处理。数据库相比较而言OLAP 系统是将较多的空间用于对数据的分类和排序,而把较少的空间用于撤消。在OLAP 系统中的大多数事务是作为批处理进程中的一部分存在的,代之以为用户输入提供大量的输入撤消区域,你会采用一个很大的撤消区域用以加载,这样可以实现离线工作以减少工作负荷。


    批量载入与事务处理进程
    对于SQL 语句和数据库而言的一个重要的性能因素是处理的类型和它在数据库中所占用的空间。一种处理类型为OLTP 它已经在今天的早些时候讨论过了,当我们谈到事务处理过程时我们是指两种输入方法(用户输入和批量载入)。
    正常情况下用户的输入是由INSERT UPDATE DELETE 语句组成的,这种类型的事务其性能通常是依据最终用户或客户而定的,最终用户通常使用前端应用程序来与数据库进行交互,所以他们很少能够看到SQL 语句,然而SQL 代码仍然通过他们所使用的前端应用程序产生了。
    当我们优化数据库的性能时我们的重点应该在最终用户的事务上,毕竟没有用户就是没有数据库,你也将会失业,你一定要力争让你的用户感到高兴即使他们对数据
    库或系统的期望有些时侯是不合情理的。对最终用户需要考虑的是最终用户输入的并发数量。在你的数据库中用户并发操作越多数据库性能下降的可能性就越大,

    什么是批量载入呢?

    批量载入就是在一次事务中完成对数据库所进行的任务,例如如果你想把上一年的记录存入一个很大的历史表中,你需要在你的历史表中插入成千上万条的记录,你大概不想手工来完成这个工作,所以你会创建一个批任务或是一个脚本来自动完成。这个工作对于批量装入数据是有很多的技术可以使用的,批量载入由于它对系统资源和数据库资源占用而名声不好,这些数据库资源包括表的访问系统目录的访问,数据库回退和排序空间,系统资源则包括CPU 和共享内存的占用,根据你所使用的操作系统和数据库服务可能还有许多麻烦的工作,最终用户事务与批量载入对于大多数数据库来说是成功的必备,但是当这两种类型的过程死锁时你的数据库系统会面临严重的性能考验,所以你应该知道它们之间的不同,如果可能最好对它们进行隔离。例如当最终用户活动处于高峰时你不应该向数据库中装入大量的数据,数据库的响应会因为并发用户的增多而变慢,你要在最终用户访问最少的时候执行批量载入任务,许多公司都选择在夜间或是早上执行批量载入任务以避免与日间进程产生冲突。
    对于大量的批量载入你一定要安排好时间,要认真的避开数据库可能进行常规用户访问的时间。

    下表给出的当重载批处理任务进行时,又有多个用户进行访问所引出资源引用冲突的情况:

    image
    正如你所看到的,许多进程在争用系统的资源,重载的批处理任务已经打破了这种平等的情况,系统将不能为每一个用户平均地分配资源,批处理任务已经大量地占用了它们,这种情况只是资源争夺的开始,如果批处理任务进行下去用户的进程可能会在最后被迫退出,这副图这在生意上是非常不利的,即使系统中只有一个用户这种竞争也还是会出现。
    使用批处理进程的另外一个问题是当另一个用户访问它所访问的表时可能会死锁,如果一个表被锁住了用户将会被拒绝访问直到批处理进程解除对该表的锁定,这可能会是几个小时的时间,如果可能批处理进程应该是系统处理最佳的时候发生不要让用户与批处理进程进行竞赛,没有人会在这样的比赛中获胜。

    删除索引以优化数据的载入
    一种可以加快批量更新速度的方法是删除索引。设想一下如果历史表的记录有上千条而且它还可能有一个甚至更多的索引,你认为索引会怎样?你通常会认为索引可以加快表的访问速度,但是在批量载入的时候将索引删除的好处可能会更大。
    当你通过索引向表中装放数据的时候你通常会希望尽可能地使用索引,尤其是当你要更新的记录在表中所占的比率很高的时候那么让我们来看一下这种方法,如果我们学习一本以后续指引的书的话你也许会发现从头至尾地看这本书要比用索引来定位你的关注点更快。如果你所要关注的东西所占的比重占全书中的比重比较小的时候索引是更有效的。
    为了让数据占总表比重相当的批量载入达到最大效率你可以使用下边的三步来使索:
    引失去作用:
    1 删除适当的索引
    2 装入或更新表中的数据
    3 重新生成表的索引


    经常使用 COMMIT 来让 DBA 走开
    当你在执行一个批量事务时你必须知道要多长时间执行一回 COMMIT 命令,COMMIT 可以将事务中所作的任何改变写到实际的表中,但是在后台它做的工作不只如此,在数据库中有一个区域是用以存储全部的写到实际表中之前的事务数据的,ORACLE 将这一区域叫做ROLLBACK 段,当你执行一个COMMIT 命令以后与你的SQL 相关联的事务会将ROLLBACK 段中的内容写到实际的表中然后更新这一区域,ROLLBAKC 段中的原有内容就被删除了,ROLLBACK命令是另一种清除ROLLBACK段的命令方法,只是它不将所做的改动写到目标表中。
    如你所料如果你一直不执行COMMIT 或ROLLBACK 命令那么事务就会一直保存在ROLLBACK 段中,随之而来的是如果你要装入的数据大小比ROLLBACK 段的可用
    空间还要大,数据库将会终止并挂起,所有的活动事务不运行COMMIT 命令是通用程序的一个缺陷,有规律地使用COMMIT 命令将会使数据库系统输入的性能稳定。
    对ROLLBACK 的管理是数据库管理员DBA 的一项复杂而重要的责任,因为事务对ROLLBACK段的影响是动态的,随后是像个别的SQL 语句一样影响数据库的整体性能。
    所以当你批量载入大量数据的时候要确保按一定的规律执行COMMIT 命令,由你的数据库管理进行检查并告诉你应该多久执行一次COMMIT 命令,见下图:

    image
    你在上图中也看到了,当用户执行一个事务的时候所做的改动是保存在ROLLBACK段中的。


    在动态环境中重新生成表和索引
    在大型数据库系统中,动态数据库环境一词的意思就是状态在不断地改变,我们在批处理进程和日常事务处理过程中会经常使用这种改变。

    动态数据库通常很定于OLTP 系统,但是也可以在DSS 或数据仓库中引用它,这要视需载入的数据的量和频度而定,结果是数据库中持续不断的大量数据的改变从而造成大量的碎片,如果管理不当这些碎片就很容易失去控制。ORACLE 在表最初生成时为它分配了一个长度当数据载入并填充完初始长度以后,初创建的表会得到下一个分配的长度,表和索引的大小。

    它对SQL 语句性能的影响是很大的,首先要进行正确的管理,所分配的空间应该足够表在一天中所增加的尺寸,同时也应该制定一个计划以按一定的规律对数据库进行碎片的清理工作。

    如果可能最好这成为每周的例行工作,清除关系型数据库中的表和索引的碎片在基本概念上是非常麻烦的:
    1 对表和索引进行完善的备份
    2 删除表和索引
    3 用新的分配空间来重新生成表和索引
    4 将数据恢复到新建的表中
    5 如有必要,重新生成索引
    6 对该表重新分派用户的规则和权限
    7 直到你已经确认了新生成的表是完全正常的,否则请保留备份,如果你选择了放弃对原始表的备份,你要在新表的数据完全恢复后马上做一个备份。
    警告:当你还没有确认新表已经完全正常之前千万不要丢弃原有的备份。

    下边给出了一个ORACLE 数据库中邮件清单表的实际的真实例子:

    CREATE TABLE MAILING_TBL_BKUP AS
    SELECT * FROM MAILING_TBL; // Table Created.
     
    drop table mailing_tbl; // Table Dropped.
     
    CREATE TABLE MAILING_TBL
    ( 
       INDIVIDUAL_ID VARCHAR2(12) NOT NULL
       INDIVIDUAL_NAME VARCHAR2(30) NOT NULL
       ADDRESS VARCHAR(40) NOT NULL
       CITY VARCHAR(25) NOT NULL
       STATE VARCHAR(2) NOT NULL
       ZIP_CODE VARCHAR(9) NOT NULL
    ) 
    TABLESPACE TABLESPACE_NAME
    STORAGE 
    ( 
       INITIAL NEW_SIZE
       NEXT NEW_SIZE
    ); // Table created.
     
    INSERT INTO MAILING_TBL select * from mailing_tbl_bkup; // 93,451 rows inserted.
     
    CREATE INDEX MAILING_IDX ON MAILING TABLE
    ( 
       INDIVIDUAL_ID 
    )
    TABLESPACE TABLESPACE_NAME
    STORAGE 
    ( 
       INITIAL NEW_SIZE
       NEXT NEW_SIZE 
    ); // Index Created.
     
    grant select on mailing_tbl to public // Grant Succeeded.
     
    drop table mailing_tbl_bkup; // Table Dropped.
     
    -- 重新生成表和索引可以让你的存储空间达到最优化,这将会提高整体的性能
    -- 切记只有当你确认新生成的表正确无误以后才可以删除原有表的备份
    -- 而且你也应该知道你用另一种方法达到了相同的结果

    数据库的调整
    调整数据库就是将数据库的服务优化的过程。如果你刚开始使用 SQL, 那么除非你是数据库管理员,或是刚刚接触关系型数据库的数据库管理员,否则你不应直接面对数据库的调整,不管你是不是数据库管理员也不管你会不会使用SQL 来在应用程序中编程。

    如果想让所有的部分协同工作,通常的调整技巧有以下几点:
    将数据库所需的全部大小最小化:在设计时预留出增长的空间很好,但是不要对此过于迷恋,不要将你以后数据库的增长空间与资源强行捆绑。
    对用户进程进行可用时间片试验:这样你可以为不同的用户分配不同的可控时间。
    优化你所使用的应用的网络包的尺寸:要通过网络传送大量的数据应该设定网络的最大包尺寸。
    将大表分配于不同的磁盘上:如果并发用户访问位于多个磁盘上的大表,等待系统资源的机会就会减少。
    将数据库的排序区、系统目录区、撤消区分布于不同的磁盘上:这些区域是用户访问最多的区域,把它放在多个硬盘上你可以最有效地利用资源。
    增加CPU:这样系统管理及数据库的性能将会得到极大的提高,增加CPU 可以提高数据处理的速度是显而易见的,如果你的机器上有多个CPU,那么你将有机会行使并行处理策略,关于并行处理请参考你的数据库相关文档中的更详细的信息,如果它在你的环境中是可用的话。
    增加内存:一般说来这样会更好。

    将表和索引存贮在不同的硬盘上:只要有可能你就应该将索引和与它相关的表存储在不同的硬盘上,这种安排可以在读表的同时访问与该表相关的索引,存储在多个硬盘上的对象的实际能力取决于有多少块硬盘连接于控制器上。

    下图给出的如何隔离数据库各个主要区域的简单例子:

    image

    在上图中使用了四个设备,从DISK01 到DISK04 ,这样做的目的是保证每个盘都有较高的访问率。
    DISK01:系统目录中存储着关于表索引,用户统计信息,数据文件的名字,大小,增加长度以及其它的相关数据,它在事务中被访问的次数相当多。
    DISK02:每天的每一次对表的内容的改变,插入,更新,删除都会更新事务的历史记录信息,事物记录是在线事务的一项重要功能,但它在只读型的数据库如DSS 或数据仓库中的意义不大。
    DISK03:ROLLBACK 段对于事务处理环境的意义也很大,可是如果很少进行事务活动的话ROLLBACK段就不会被经常使用。
    DISK04:这里是数据库排序区,也就是说它是SQL 语句过程和排序数据如GROUP BY或ORDER BY 子句的临时存放区域。DSS 和数据仓库是排序区域的典型代表,但是在事务处理环境中也考虑使用排序区域。
    技巧:你也应该注意到数据库的表和索引是如何入到每一个磁盘上的,应该尽可能地将表和索引分开,注意在上图中表和索引是被安排在不同的设备上的,你也可以看到大表和索引在不同设备上的交互访问,这种技术将大表分为可以访问的小段,交互访问表和索引是一种控制碎片的办法,在这种情况下可以在参考相关索引的同时进行读表,这就会提高数据的整体访问速度。
    这个例子的确是非常简单的,根据你所使用的数据库的函数大小和相互关系,你可以找到类似的方法对系统进行优化以提高工作性能。如果钱不是问题那么完美的方法是将每一个数据库实体都放在一个硬盘上,包括大表和索引。
    对数据库的调整要依据你所使用的数据库系统而定,显而易见优化查询要比调整数据库的作用更明显,也就是说当你还没有将SQL 应用本身调整好时,你不要期望在对数据库的调整上得到太多的回报,以调整数据库为专职的人员会专攻一种数据库产品以学习尽可能多的关于它的特点和特性,尽管数据库的调整经常被认为是一项痛苦的工作,但是它可以让真正了解它的人对它更充分地利用。

    性能的障碍
    我们已经说过许多的对一个数据库性能产生影响的可能方面,最具有代表性的瓶颈涉及到系统级的维护,数据库的维护和对SQL 语句的管理。
    这里总结了常见的大多数对系统性能和数据库响应时间有影响的因素:
    没有很好地利用服务器上的可用设备:电脑可能基于某种原因已经购买了多个磁盘,如果你没有将一些数据库的重要组件分布在多个磁盘上的话性能就会受到影响,要让系统的能力和数据库服务的能力尽可能地发挥。
    没有经常性的执行COMMIT 命令:懒于使用 COMMIT 命令和 ROLLBACK 命令的结果会导致你的服务器出现瓶颈。

    允许批量载入与日常进程同时工作:当数据库还存在其它用户时,运行批量载入会对每个人都产生影响,批处理进行会由于成为最终用户和系统资源之间的瓶颈。
    在创建SQL 语句时不认真:不负责任地创建复合语句会比标准语句耗用更多的系统时间。
    对于有索引的表运行批处理任务:你可能会需要几天几夜才能完成一个批处理的任务,而一般的批量载入任务也许只要几个小时,索引会对批量载入任务访问表中更多的行造成障碍。
    可分配的存储空间中有更多的并发用户:随着当前数据户用户和系统用户的增多你可能会因为过程的共享而需要更多的内存。
    创建索引的列只存在不多的可选数值:对如性别这样的列创建索引并不会非常有效,所以你所创建的索引返回的行数应该占表的并行数比较低。
    对小表创建了索引:这时使用全表扫描可能会更有效。
    没有有效地管理系统的资源:对系统资源的管理不善,如数据库初始化表的创建,不受控制的碎片和不正确的系统维护会浪费大量的数据空间。
    表和索引的大小不合适:在大型数据库中对表和索引的大小估计错误,如果护理不当会带来严重的碎片问题并会由此而引发更严重的问题。

    内置的调整工具
    在确认需要进行调整时要征徇DBA 和你的数据库供应商以得知哪些工具对你是可用的。你可以使用调整工具来确定你的数据库在数据访问上的不足之处,此外这些工具对对于特定的SQL 语句提出更改建议以提高系统的性能。
    ORACLE 有两个流行的工具用以管理SQL 语句的性能,这两个工具是 EXPLAIN PLAN 和 TKPROF。 EXPLAIN PLAN 可以在SQL 语句执行时检查它的访问路径,TKPROF 可以给出每个SQL 语句在执行时所需的时间。ORACLE 公司也提供了其它的工具用以对SQL语句和数据库进行分析,但是这两种是最流行的。

  • 相关阅读:
    【从零开始学Java笔记】学生管理系统
    【从零开始学Java笔记】关键字super和this
    【从零开始学Java笔记】关键字Static
    【从零开始学Java笔记】关键字final
    【从零开始学Java笔记】关键字abstract
    循环结构
    switch选择结构
    if条件语句
    位运算
    Eclipse 报错The method xxx of type must override a superclass method、Description Resource Path Location Type Java compiler level does not match the version of the installed Java project facet
  • 原文地址:https://www.cnblogs.com/SkySoot/p/2439431.html
Copyright © 2020-2023  润新知