一、数据库结构的设计
表的设计具体注意的问题:
1、数据行的长度不要超过 8020 字节,如果超过这个长度的话在物理页中这条数据会占用两行从而造成存储碎片,降低查询效率。
2、能够用数字类型的字段尽量选择数字类型而不用字符串类型的(电话号码),这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接回逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
3、对于不可变字符类型 char 和可变字符类型 varchar 都是 8000 字节, char 查询快,但是耗存储空间,varchar 查询相对慢一些但是节省存储空间。在设计字段的时候可以灵活选择,例如用户名、密码等长度变化不大的字段可以选择 CHAR,对于评论等长度变化大的字段可以选择 VARCHAR。
4、字段的长度在最大限度的满足可能的需要的前提下,应该尽可能的设得短一些,这样可以提高查询的效率,而且在建立索引的时候也可以减少资源的消耗。
二、查询的优化
保证在实现功能的基础上,尽量减少对数据库的访问次数(可以用缓存保存查询结果,减少查询次数);通过搜索参数,尽量减少对表的访问行数, 最小化结果集,从而减轻网络负担;能够分开的操作尽量分开处理,提高每次的响应速度;在数据窗口使用 SQL 时,尽量把使用的索引放在选择的首列;算法的结构尽量简单;在查询时,不要过多地使用通配符如 SELECT*FROMT1 语句,要用到几列就选择几列如:SELECTCOL1,COL2FROMT1;在可能的情况下尽量限制尽量结果集行数如:SELECTTOP300COL1,COL2,COL3FROMT1, 因为某些情况下用户是不需要那么多的数据的。
1. 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num is null
可以在 num 上设置默认值 0,确保表中 num 列没有 null 值,然后这样查询:
select id from t where num=02. 应尽量避免在 where 子句中使用!= 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描。优化器将无法通过索引来确定将要命中的行数, 因此需要搜索该表的所有行。
3. 应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num=10 or num=20
可以这样查询:
select id from t where num=10
union all
select id from t where num=204.in 和 not in 也要慎用,因为 IN 会使系统无法使用索引, 而只能直接搜索表中的数据。如:
select id from t where num in(1,2,3)
对于连续的数值,能用 between 就不要用 in 了:
select id from t where num between 1 and 35. 尽量避免在索引过的字符数据中,使用非打头字母搜索。这也使得引擎无法利用索引。
见如下例子:
SELECT*FROMT1WHERENAMELIKE ‘%L%’
SELECT*FROMT1WHERESUBSTING(NAME,2,1)=’L’
SELECT*FROMT1WHERENAMELIKE ‘L%’
即使 NAME 字段建有索引,前两个查询依然无法利用索引完成加快操作,引擎不得不对全表所有数据逐条操作来完成任务。而第三个查询能够使用索引来加快操作。
6. 必要时强制查询优化器使用某个索引,如在 where 子句中使用参数,也会导致全表扫描。因为 SQL 只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:
select id from t where num=@num
可以改为强制查询使用索引:
select id from t with(index(索引名)) where num=@num
7. 应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
SELECT*FROMT1WHEREF1