(8)Hash Join (HJ )由于须做HASH 运算,索引的存在对数据查询速度几乎没有影 响。
(9)在主键上建立索引,尤其当经常用它作为连接的时候;在经常用于连接而又未指 定为外键的列上建立索引。
(10)经常同时存取多列,且每列都含有重复值,可以考虑建立复合索引来覆盖一个或 一组查询,并且把查询引用最频繁的列作为前导列。
(11)尽使用较窄的索引,这样数据页每页上能因存放较多的索引行而减少操作。
(12)并行查询将不会用到索引。
(13)索引中存储值不能为全空。
(14)查询中较少用到的列、数据量较大的列均不应建立索引。
5.SQL 语句优化
在完成了系统设计、索引设计等工作以后,就要考虑在使用过程中对语句的设计了。 影响数据库应用程序性能的一个重要因素是SQL 语句,按其影响严重程度,依次可分为: 无谓的SQL,拙劣的SQL,复杂的SQL。 无谓的SQL:它们对数据库的访问,并不存在技术、技能上的问题,但却不是必要的, 超出了实际业务需求。其结果是浪费了宝贵的主机资源、占用了网络流量,降低了系统性能。 拙劣的SQL:它们对数据库的访问并不是多余的,所体现的业务逻辑或结果是正确的, 但是“写法”不够好,导致数据库处理起来不够优化。 复杂的SQL:数据库中多表(或视图)关联,条件复杂、冗长,计算复杂,使用冷僻 的SQL 技术等。 其中,无谓的SQL 和拙劣的SQL 属于开发技能方面的问题;复杂的SQL 属于设计技 能方面的问题,设计到数据库的结构。 在使用结构化查询语言来执行查询时,推荐以下举措:
(1)择运算应尽可能先做,并在对同一个表进行多个选择运算时,选择影响较大的语 句放在前面;较弱的选择条件写在后面,这样就可以先根据较严格的条件得出数据较小的 信息,再在这些信息中根据后面较弱的条件得到满足条件的信息。
(2)应避免使用相关子查询。把子查询转换成联结来实现。对于主查询的每一条记录子 查询都要执行一次,嵌套的层次越多效率越低。避免对子句使用数学运算符。即不要对数 据表的属性列进行操作。SQL 概念上将位于WHERE 子句中的相关子查询,处理成获取参 数并且返回一个单独的值或值的集合的函数。因为子查询要对应位于外层查询的每一个元组 进行单独的计算。从而导致大量的随机磁盘I/O 操作。所以在实际应用中若可以用连接代替 的子查询,则用连接实现。例如,有以下相关子查询语句:
SELECT ProductName FROM Products WHERE EXISTS (SELECT * FROM OrderDetails WHERE Discount >= 25 AND Products.ProductID= OrderDetails.ProjectID) ; |
用连接查询实现如下:
SELECT ProductName FROM Products , OrderDetails WHERE Discount >= 25 AND Products.ProductID= OrderDetails.ProjectID |
(3)字段提取按照“ 需多少,提多少” 的原则,避免“SELECT *”。“SELECT *”需 要数据库返回相应表的所有列信息,这对于一个列较多的表无疑是一项费时的操作。
(4)避免使用!=(或<>)、IS NULL 或IS NOT NULL、IN、NOT IN等这样的操作符,避免在WHERE 子句中使用非聚合表达式。这些操作符会使系统无法使用索引,而只能直接搜 索表中的数据。例如,SELECT id,name FROM employee WHERE id!=B% 优化器将无法通过索引来确定将要命中的行数,因此需要搜索该表的所有行。
(5)避免使用OR,用UNION 代替。OR 语句的执行原理并不是利用列上的索引根据每 个语句分别查找再将结果求并集,而是先取出满足每个OR 子句的行,存入临时数据库的 工作表中,再建立唯一索引以去掉重复行,最后从这个临时表中计算结果。这样使用可能 造成索引失效,导致顺序扫描整个表,大大降低查询效率。
(6)在执行连接前对关系作适当的预处理,预处理的方法有两种,在连接属性上建立 索引和对关系进行排序。
(7)将一个大的查询拆成多步执行查询。
(8)如果应用程序使用循环,可考虑在查询内放入循环。