经常听到有做应用的朋友抱怨数据库的性能问题,比如非常低的并发,令人崩溃的响应时间,长时间的锁等待,锁升级 , 甚至是死锁,等等。在解决这些问题的过程中,DBA 经常发现应用开发人员对数据库的“误用”。包括 , 返回过多不必要的数据 , 不必要和不适当加锁,对隔离级别的误用和对存储过程的误用等等。但是,面对浩如烟海的数据库知识 , 要求完全掌握 , 对应用开发人员来说也确实枯燥艰深 . 因此,笔者特别提炼对应用开发人员有帮助的 SQL 书写部分,以期望能对数据库开发人员有所帮助。
“根据我们的经验(由很多业界专家证明),在 SQL Server 上取得的性能提高有 80% 来自对 SQL 编码的改进,而不是来自于对于配置或系统性能的调整。”
—凯文 克莱恩等,Transact-SQL Programming 作者
“经验表明 80%-90% 的性能调优是在应用级做的,而不是在数据库级”
—托马斯 白特,Expert One on One: Oracle 作者
本文将主要讨论基于语法的优化以及简简单的查询条件。基于语法的优化指的是为不考虑任何的非语法因素(例如,索引,表大小和存储等),仅考虑在 SQL 语句中对于词语的选择以及书写的顺序。
这一部分,将看一下一些在书写简单查询语时需要注意的通用的规则。
最好的查询语句是将简单的比较操作作用于最少的行上。以下两张表,表 1 和表 2 以由好到差的顺序列出了典型查询条件操作符并赋与权值。
表 1. 查询条件中操作符的权值
| 操作符 | 权值 |
| = | 10 |
| > | 5 |
| >= | 5 |
| < | 5 |
| <= | 5 |
| LIKE | 3 |
| <> | 0 |
表 2. 查询条件中操作数的权值
| 操作数 | 权值 |
| 仅常量字符 | 10 |
| 仅有列名 | 5 |
| 仅有参数 | 5 |
| 多操作数表达式 | 3 |
| 精确数值类型 | 2 |
| 其它数值类型 | 1 |
| 时间数据类型 | 1 |
| 字符数据类型 | 0 |
| NULL | 0 |
根据表 1 和表 2 中分配的权值,可以看出最好的查询条件应该是像下面这样的:
… WHERE smallint_column = 789 |
这个例子得到 27 分,计算如下:
- 左侧只有列名(smallint_column)得 5 分
- 操作数为精确数据类型(smallint_column)得 2 分
- 等号(=)操作符得 10 分
- 右侧是文字字符(789)得 10 分
下面是另外一个例子
… WHERE char_column >= varchar_column || ‘ x ’ |
这种类型的查询权值得分就很低,只有 13 分
- 左侧只有列名(char_column)得 5 分
- CHAR 类型的操作数得 0 分
- 大于等于操作符得 5 分
- 左侧是多操作数表达示得 3 分
- VARCHAR 类型的操作数得 0 分
上面表格中的权值数可能在不同类型的数据库系统中会有所不同,所以记住这些具体数值是没有意义的,只需要了解它们的排序即可。用时越少的比较条件,得分也就越高,这样的比较条件通常是那些操作的行数少或者易于比较的。
传递法则是这样定义的:
IF (A <comparison operator> B) IS TRUE AND (B <comparison operator> C) IS TRUE THEN (A <comparison operator> C) IS TRUE AND NOT (A <comparison operator> C) IS FALSE |
