IBM DB2数据库SQL编码优化的基础教程经典版! |
本文标签:IBM DB2数据库 以下的文章主要介绍的是IBM DB2数据库SQL编码优化的基础教程,这种特定查询的重要性即为,查询越重要,您可能就越应该通过创建索引来对其进行调优 。如果您正在编码 CIO 要每天都运行的查询,那么您应该确保它提供最佳性能 。 因此,为该特定查询构建索引是很重要的 。反之,职员的查询也许就没有必要看得那么重,所以也许应该利用现有索引来执行查询 。当然,决定取决于应用程序对业务的重要性 - 而不只是用户的重要性 。
索引设计涉及的内容比到目前为止我所讨论的要多得多 。例如,您也许要考虑索引重载以实现仅索引访问(index-only access) 。如果 SQL 查询要寻找的所有数据都包含在索引中,那么 DB2 也许只使用索引就可以满足该请求 。请考虑我们前面的 SQL 语句 。给定了关于 EMPNO 和 DEPTNO 的信息,我们要寻找 LASTNAME 和 SALARY 。
我们还从创建关于 EMPNO 和 DEPTNO 列的索引开始 。如果我们在索引中还包含了 LASTNAME 和 SALARY,我们就不再需要访问 EMP 表,因为我们需要的所有数据都已经在索引中 。该技术可以大大提高性能,因为它减少了 I/O 请求的数量 。 请记住:使每个查询成为仅索引访问是不谨慎,甚至也是不可能的 。您应该谨慎使用该技术以便用于特别棘手或重要的 SQL 语句 。
SQL 编码准则
当您编写访问 DB2 数据的 SQL 语句时,要确保遵循以下三个编码 SQL 的准则以获得最佳性能 。当然,SQL 性能是一个复杂的话题,而且了解 SQL 的执行方式的每一个细微差别可能要花一生的时间 。但是,这些简单的规则可以使您进入开发高性能 DB2 应用程序的正轨 。
第一条规则是始终在每条 SQL SELECT 语句的 SELECT 列表中只提供 确实需要检索的那些列 。另一种说法就是“不要使用 SELECT *” 。简写 SELECT * 表示您要检索正在被访问的表中的所有列 。这适用于“快捷但不恰当的方式获得的“(quick and dirty)查询,但却是应用程序的坏实践,因为:
DB2 表在将来可能需要更改,以包括附加列 。SELECT * 也会检索那些新的列,而如果没有进行费时的更改,您的程序也许无法处理附加的数据 。
DB2 将为被请求返回的每一列消耗附加资源 。如果程序不需要数据,它就不会寻找它 。即使程序需要每一列,最好根据 SQL 语句中的名称来显式地寻找每一列,以便增加清晰度和避免以前犯的错误 。
不要寻找您已经知道的东西 。这听起来似乎显而易见,但大多数程序员都曾经违反过这条规则 。举一个典型的示例,考虑以下 SQL 语句有什么错误:
放弃吗?问题是 EMPNO 已经包含在 SELECT 列表中 。您已经知道了 EMPNO 将等于值“000010”,因为那就是 WHERE 子句要 DB2 做的事 。但在 WHERE 子句中列出了 EMPNO,DB2 还会尽职地检索该列 。这会产生附加开销,从而降低性能 。
在 SQL 中 使用 WHERE 子句过滤数据 ,而不是在程序中到处使用它进行过滤 。这也是新手容易犯的错误 。在 DB2 将数据返回到程序之前,最好由 DB2 过滤数据 。这是因为 DB2 使用附加 I/O 和 CPU 资源来获取每一行数据 。传递到程序的行越少,SQL 的效率就越高:
与只读取所有数据而不使用 WHERE 子句,然后在程序中检查 SALARY 是否大于 50000.00 的做法相比,该 SQL 更好 。
使用参数化查询 。参数化 SQL 语句包含了变量,也称作参数(或参数标记) 。典型的参数化查询使用这些参数来代替文字值,因此 WHERE 子句条件可以在运行时更改 。通常程序被设计成最终用户可以在运行查询之前提供参数的值 。这允许使用一个查询根据提供给参数的不同的值返回不同的结果 。
参数化查询的主要性能好处是优化器可以制定在重复执行语句时能够再使用的存取路径 。与每次 WHERE 子句中需要一个新值就发出一条全新的 SQL 语句相比,这可以给程序增加很大的性能收益 。
但是,这些规则并不是 SQL 性能调优的最终和最高目标 - 决不是 。您可能需要附加的、深入的调优 。但遵循前面的规则将确保您不会犯降低应用程序性能的“新手”错误 。
特定IBM DB2数据库应用程序开发技巧
无论您使用的是 Delphi、C++Builder 还是 Kylix,某些技巧和准则将帮助您确保在访问 DB2 数据时获得好的性能 。例如,在某些情况下,使用 dbExpress TM来代替 ODBC/JDBC 或 ADO 可以提高查询性能 。dbExpress 是用于从 Delphi(或 Borland Kylix™)处理动态 SQL 的跨平台接口 。
要确保在您的应用程序中经常发出 COMMIT 语句 。COMMIT 语句控制工作单元 。发出 COMMIT 会将自上一个 COMMIT 语句之后的所有工作“永远”记录到IBM DB2数据库中 。在发出 COMMIT 之前,可以使用 ROLLBACK 语句回滚工作 。 当修改数据(使用 INSERT、UPDATE 和 DELETE)但没有发出 COMMIT 时,DB2 将在数据上加一把锁并保持该锁 - 这把锁会使其它应用程序在等待检索被锁住的数据时超时 。通过在工作完成时发出 COMMIT 语句,并且确保数据是正确的,就释放了该数据以供其它应用程序使用 。
另外,构建应用程序时要考虑使用情况 。例如,当某个特定查询返回几千行给最终用户时,要慎重处理 。对于在程序和最终用户之间的在线交互,很少会用到几百行以上的数据 。您可以在 SQL 语句上使用 FETCH FIRST nROWS ONLY 子句来限制返回到查询的数据量 。例如,考虑以下查询:
该查询将只返回 200 行 。如果有超过 200 行符合条件也没有关系;如果您尝试从查询中 FETCH(访存)超过 200 行,DB2 将用 +100 SQLCODE 表明数据结束 。当您想要限制返回给程序的数据量时,这种方法很有用 。
DB2 支持另一个名为 OPTIMIZE FOR nROWS 的子句,该子句不限制要返回给游标的行数,但从性能角度看可能是有帮助的 。使用 OPTIMIZE FOR nROWS 子句告诉 DB2 如何处理 SQL 语句 。例如:
这告诉 DB2 尝试尽快访存前 20 行 。如果您的 Delphi 应用程序在显示从IBM DB2数据库检索出来的数据行时每次显示 20 行,那么这将非常有用 。
对于只读游标,使用 FOR READ ONLY 子句确保游标无歧义 。Delphi 不能在 DB2 游标中执行位置更新,因此将 FOR READ ONLY 附加到每条 SELECT 语句后面可以使游标成为无歧义的只读游标,从而对 DB2 有所帮助 。例如:
结束语
了解 SQL 编码以获得最佳性能的基础知识将使您的 Delphi 企业应用程序的性能立即得到增长 。但我只揭露了冰山一角 。您需要学习日益增多的 SQL 的复杂类型,包括连接、子选择和联合等 。您还需要学习如何最好地编写这些 SQL 语句以及如何发现 DB2 选择的存取路径来满足您的 SQL 请求 。确实,还有许多要学习 。但是您已经学习了一些如何最大限度地利用 DB2 SQL 的初步知识,尽情地享用这些知识吧 。
|