1
SQL语句原则
1.1 查看sql语句的执行路径和开销
检查执行路径中是否有全表扫描的执行计划或者cost开销太大,若有,则需要考虑修改sql语句或增加索引。
1.2 不要打开大的数据集
一个经常被提出的问题是:怎样才能迅速的将100000条记录添加到ComboBox中?这是不对的,不能也不需要这样做。很简单,你的用户要浏览100000条记录才能找到需要的记录。在这里,需要的是一个更好的UI,你需要为你的用户显示不超过100或200条记录
1.3 不要使用SELECT *
这点不太容易做到,我太了解了,因为我自己就经常这样干。可是,如果在SELECT中指定你所需要的列,那将会带来以下的好处:
1 减少内存耗费和网络的带宽
2 你可以得到更安全的设计
3 给查询优化器机会从索引读取所有需要的列
1.4 避免在索引列上使用IS NULL和IS NOT NULL
不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。
任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的
1.5 总是使用索引的第一个列
如果索引是建立在多个列上, 只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引. 这也是一条简单而重要的规则,当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引 。
1.6 带通配符(%)的like语句
同样以上面的例子来看这种情况。目前的需求是这样的,要求在职工表中查询名字中包含cliton的人。可以采用如下的查询SQL语句:
select * from employee where last_name like '%cliton%';
这里由于通配符(%)在搜寻词首出现,所以Oracle系统不使用last_name的索引。在很多情况下可能无法避免这种情况,但是一定要心中有底,通配符如此使用会降低查询速度。然而当通配符出现在字符串其他位置时,优化器就能利用索引。在下面的查询中索引得到了使用:
select * from employee where last_name like 'c%';
1.7 where条件中字段名不要有运算或函数,否则会不能利用索引从而导致全表扫描
如果一定要用函数,需通知数据库管理员,考虑是否需要增加函数索引。
看下面两个条件:
Table.column * 12 > 24000
Table.column > 24000/12
这时应该按第二个方法写。同样,不要对字段直接使用函数,可以尝试对该字段要比较的常量或变量进行处理。
1.8 最好不要用关联子查询,因为关联子查询耗费大量的cpu
1.9 在sql语句的where子句中,尽量化解not操作;
1.10 使用有前导字符的like运算符来代替substr函数
除非已建立了substr的函数索引,否则将导致该列上的索引无效。
1.11 对于带有许多or条件的非常复杂的查询,可考虑用union all重写,
可查看执行路径,比较两种方式的开销cost哪个大即可。
1.12 有索引的尽量用索引,有用到索引的条件写在前面,条件严格的放在前面,尽量避免进行全表扫描,限制条件尽可能多,以便更快搜索到要查询的数据
1.13 在java中一定用prepare statement。所有的变量都应该做bind
Sql语句执行后是放在share_pool_size中.如果输入的变量直接拼在字符串里的话,那么每执行一次该变量不同取值的该sql后,share_pool_size中都将存入一条该静态语句。但是如果变量都做bind的话,share_pool_size中将只存放一次该语句。这样将节省sga的开销。
1.14 大量的排序操作影响系统性能,所以尽量减少order by和group by排序操作
如必须使用排序操作,请遵循如下规则:
(1) 排序尽量建立在有索引的列上。
(2) 如结果集不需唯一,使用union all代替union。
1.15 索引的使用
(1) 尽量避免对索引列进行计算。如对索引列计算较多,请提请系统管理员建立函数索引。
(2) 尽量注意比较值与索引列数据类型的一致性。
(3) 对于复合索引,SQL语句必须使用主索引列
(4) 对于索引的比较,尽量避免使用NOT=(!=)
(5) 查询列和排序列与索引列次序保持一致
1.16 用多表连接代替EXISTS子句
举例如下:
X SELECT ......
FROM emp
WHERE EXISTS ( SELECT 'X'
FROM dept
WHERE dept_no=e.dept_no
AND dept_cat='A');
O SELECT ......
FROM emp e,dept d
WHERE e.dept_no=d.dept_no
AND dept_cat='A';
1.17 使用UNION ALL、MINUS、INTERSECT提高性能
1.1 查看sql语句的执行路径和开销
检查执行路径中是否有全表扫描的执行计划或者cost开销太大,若有,则需要考虑修改sql语句或增加索引。
1.2 不要打开大的数据集
一个经常被提出的问题是:怎样才能迅速的将100000条记录添加到ComboBox中?这是不对的,不能也不需要这样做。很简单,你的用户要浏览100000条记录才能找到需要的记录。在这里,需要的是一个更好的UI,你需要为你的用户显示不超过100或200条记录
1.3 不要使用SELECT *
这点不太容易做到,我太了解了,因为我自己就经常这样干。可是,如果在SELECT中指定你所需要的列,那将会带来以下的好处:
1 减少内存耗费和网络的带宽
2 你可以得到更安全的设计
3 给查询优化器机会从索引读取所有需要的列
1.4 避免在索引列上使用IS NULL和IS NOT NULL
不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。
任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的
1.5 总是使用索引的第一个列
如果索引是建立在多个列上, 只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引. 这也是一条简单而重要的规则,当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引 。
1.6 带通配符(%)的like语句
同样以上面的例子来看这种情况。目前的需求是这样的,要求在职工表中查询名字中包含cliton的人。可以采用如下的查询SQL语句:
select * from employee where last_name like '%cliton%';
这里由于通配符(%)在搜寻词首出现,所以Oracle系统不使用last_name的索引。在很多情况下可能无法避免这种情况,但是一定要心中有底,通配符如此使用会降低查询速度。然而当通配符出现在字符串其他位置时,优化器就能利用索引。在下面的查询中索引得到了使用:
select * from employee where last_name like 'c%';
1.7 where条件中字段名不要有运算或函数,否则会不能利用索引从而导致全表扫描
如果一定要用函数,需通知数据库管理员,考虑是否需要增加函数索引。
看下面两个条件:
Table.column * 12 > 24000
Table.column > 24000/12
这时应该按第二个方法写。同样,不要对字段直接使用函数,可以尝试对该字段要比较的常量或变量进行处理。
1.8 最好不要用关联子查询,因为关联子查询耗费大量的cpu
1.9 在sql语句的where子句中,尽量化解not操作;
1.10 使用有前导字符的like运算符来代替substr函数
除非已建立了substr的函数索引,否则将导致该列上的索引无效。
1.11 对于带有许多or条件的非常复杂的查询,可考虑用union all重写,
可查看执行路径,比较两种方式的开销cost哪个大即可。
1.12 有索引的尽量用索引,有用到索引的条件写在前面,条件严格的放在前面,尽量避免进行全表扫描,限制条件尽可能多,以便更快搜索到要查询的数据
1.13 在java中一定用prepare statement。所有的变量都应该做bind
Sql语句执行后是放在share_pool_size中.如果输入的变量直接拼在字符串里的话,那么每执行一次该变量不同取值的该sql后,share_pool_size中都将存入一条该静态语句。但是如果变量都做bind的话,share_pool_size中将只存放一次该语句。这样将节省sga的开销。
1.14 大量的排序操作影响系统性能,所以尽量减少order by和group by排序操作
如必须使用排序操作,请遵循如下规则:
(1) 排序尽量建立在有索引的列上。
(2) 如结果集不需唯一,使用union all代替union。
1.15 索引的使用
(1) 尽量避免对索引列进行计算。如对索引列计算较多,请提请系统管理员建立函数索引。
(2) 尽量注意比较值与索引列数据类型的一致性。
(3) 对于复合索引,SQL语句必须使用主索引列
(4) 对于索引的比较,尽量避免使用NOT=(!=)
(5) 查询列和排序列与索引列次序保持一致
1.16 用多表连接代替EXISTS子句
举例如下:
X SELECT ......
FROM emp
WHERE EXISTS ( SELECT 'X'
FROM dept
WHERE dept_no=e.dept_no
AND dept_cat='A');
O SELECT ......
FROM emp e,dept d
WHERE e.dept_no=d.dept_no
AND dept_cat='A';
1.17 使用UNION ALL、MINUS、INTERSECT提高性能