>>>本文主要针对Oracle
使用"*"替代所有的列,可以降低编写SQL语句的难度和减少SQL语句的复杂性,但是却降低了SQL语句执行的效率。
当一条SQL语句从客户端进程传递到服务器端进程后,Oracle需要执行如下步骤:
1、在共享池中搜索SQL语句是否已经存在。
2、验证SQL语句的语法是否准确。
3、执行数据字典来验证表和列的定义。
4、获取对象的分析锁,以便在语句的分析过程中对象的定义不会改变。
5、检查用户是否具有相应的操作权限。
6、确定语句的最佳执行计划。
7、将语句和执行方案保存到共享的SQL区。
使用"*"会导致Oracle系统需要通过数据字典将*转换成表的所有列。
在select语句中,使用where子句过滤行,使用having子句过滤分组,而行被分组需要一定的时间,所以尽量先用where过滤掉尽量多的数据。
两者都可以删除表数据,区别是:truncate会一次性删除全部数据并且不会记录操作,不可回滚;delete会逐行删除数据并且使用回滚段记录操作,在commit前可以rollback。如果确定要删除表中的所有行,建议使用truncate语句。
用户进行DML操作后,如果不使用commit命令进行提交,则Oracle会在回滚段中记录DML操作,以便用户使用rollback命令对数据进行恢复。实现这种数据回滚功能,需要花费相应的时间和空间资源。
尽量减少表的查询次数,主要是指可以使用一次查询获得的数据,尽量不要通过两次或更多次的查询获得。
in操作符用于检查一个值是否包含在列表中。exists与in不同,exists只检查行的存在性,而in检查实际的值。在子查询中,exists提供的性能通常比in提供的性能要好。因此建议用exists替代in,用not exists替代not in。
在连接查询的select语句中,distinct关键字用于禁止重复行的显示;exists用于检查子查询返回的行的存在性。尽量使用exists替代distinct,因为distinct在禁止重复行显示之前要排序检索到的行。
使用exists操作符实现子查询时,推荐使用表的连接查询来替代exists的使用方式。
使用"<"会定位到当前数,再去寻找比它小的数。
在查询中包含多个表时,为每个表指定表别名,并且为所引用的每列都显式地指定合适的列名,这称为完全限定的列引用,这减少了解析列的时间。
Oracle的解析器在处理form子句中的表时,是按照从右到左的顺序进行处理。建议在使用表的连接查询时,选择记录行数最少的表作为驱动表,也就是作为form子句中的最后一个表。
Oracle采用自右至左(自下向上)的顺序解析where子句,根据这个顺序,表之间的连接应该写在其它where条件之前,将可以过滤掉最大数量记录的条件写在where子句的末尾。
优点:当Oracle查找执行select和update语句的最佳路径时,Oracle优化器将使用索引,同时在连接多个表时使用索引也可以提高效率。
缺点:索引需要额外的存储空间和处理操作。
哪些表?
1、对于经常以查询关键字为基础的表,并且该表中的数据行是均匀分布的。
2、以查询关键字为基础,表中的数据行随机排序。
3、表中包含的列数相对比较少。
4、表中的大多数查询都包含相对简单的where子句。
哪些列?
1、经常在where子句中使用的列。
2、经常在表连接查询中用于表之间连接的列。
3、不宜将经常修改的列作为索引项。
4、不宜将经常在where子句中使用,但与函数或操作符相结合的列作为索引项。
5、对于取值较少的列,应考虑建立位图索引,而不应该采用B数索引。
注意:除了所查询的表没有索引,或者需要返回表中的所有行时,Oracle会进行全表扫描以外,如果对索引列使用了函数或操作符(例如like),Oracle同样会对全表进行扫描。
对索引列的操作语句应该尽量避免“非”操作符的使用,例如not、!=、<>、!<、!>、not exists、not in和not like等,“非”操作符的使用会造成Oracle对表进行全表扫描。
使用like时,如果第一个字符是通配符,索引不再起作用。
在where子句中使用is null或is not null,对唯一索引项进行空值比较时,Oracle将停止使用该列上的唯一索引,导致Oracle进行全表扫描。
列中包含有null值的行都不会被包含在索引中,复合索引中只要有一列含有null值,那么这一列对于此复合索引就是无效的。所以设计数据库时,尽量不要让字段的默认值为null值。
索引不仅可以基于单独的列,还可以基于多个列,在多个列上创建的索引叫复合索引。
创建复合索引时,应该按照如下原则:
选择经常在where子句中使用、并且由and操作符连接的列作为复合索引列。
选择where子句中使用频率相对较高的列排在最前面,或者根据需要为其它列创建单独的索引。
只有当复合索引中的第一列被where子句使用时,Oracle才会使用该复合索引。
通过v$object_usage视图,查看索引的使用状态。