数据库设计与SQL优化的建议

1、
用程序中,保证在实现功能的基础上,尽量减少对数据库的访问次数;通过搜索参数,尽量减少对表的访问行数,最小化结果集,从而减轻网络负担;能够分开的操作尽量分开处理,提高每次的响应速度;在数据窗口使用SQL时,尽量把使用的索引放在选择的首列;算法的结构尽量简单;在查询时,不要过多地使用通配符如SELECT
* FROM T1语句,要用到几列就选择几列如:SELECT COL1,COL2 FROM T1;在可能的情况下尽量限制尽量结果集行数如:SELECT TOP
300 COL1,COL2,COL3 FROM
T1,因为某些情况下用户是不需要那么多的数据的。不要在应用中使用数据库游标,游标是非常有用的工具,但比使用常规的、面向集的SQL语句需要更大的开销;按照特定顺序提取数据的查找。

2、避免使用不兼容的数据类型。例如float和int、char和varchar、binary和varbinary是不兼容的。数据类型的不兼容可能使优化器无法执行一些本来可以进行的优化操作。例如:

SELECT name FROM employee WHERE salary > 60000

在这条语句中,如salary字段是money型的,则优化器很难对其进行优化,因为60000是个整型数。我们应当在编程时将整型转化成为钱币型,而不要等到运行时转化。

3、
尽量避免在WHERE子句中对字段进行函数或表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:

SELECT * FROM T1 WHERE F1/2=100

应改为:

SELECT * FROM T1 WHERE F1=100*2

SELECT * FROM RECORD WHERE SUBSTRING(CARD_NO,1,4)=’5378’

应改为:

SELECT * FROM RECORD WHERE CARD_NO LIKE ‘5378%’

SELECT member_number, first_name, last_name  FROM members

WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21

应改为:

SELECT member_number, first_name, last_name  FROM members

WHERE dateofbirth < DATEADD(yy,-21,GETDATE())
即:任何对列的操作都将导致表扫描,它包括数据库函数、计算表达式等等,查询时要尽可能将操作移至等号右边。

4、避免使用!=或<>、IS NULL或IS NOT NULL、IN
,NOT IN等这样的操作符,因为这会使系统无法使用索引,而只能直接搜索表中的数据。例如:  SELECT id FROM
employee WHERE id != ‘B%’  优化器将无法通过索引来确定将要命中的行数,因此需要搜索该表的所有行。

5、
尽量使用数字型字段,一部分开发人员和数据库管理人员喜欢把包含数值信息的字段
设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接回逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

6、合理使用EXISTS,NOT
EXISTS子句。如下所示:

1.SELECT SUM(T1.C1)FROM T1 WHERE( (SELECT COUNT(*)FROM T2 WHERE
T2.C2=T1.C2>0)

2.SELECT SUM(T1.C1) FROM T1WHERE EXISTS(SELECT * FROM T2 WHERE
T2.C2=T1.C2)

两者产生相同的结果,但是后者的效率显然要高于前者。因为后者不会产生大量锁定的表扫描或是索引扫描。

如果你想校验表里是否存在某条纪录,不要用count(*)那样效率很低,而且浪费服务器资源。可以用EXISTS代替。如:

IF (SELECT COUNT(*) FROM table_name WHERE column_name = ‘xxx’)

可以写成:

IF EXISTS (SELECT * FROM table_name WHERE column_name = ‘xxx’)

经常需要写一个T_SQL语句比较一个父结果集和子结果集,从而找到是否存在在父结果集中有而在子结果集中没有的记录,如:

1.SELECT a.hdr_key  FROM hdr_tbl a—- tbl a 表示tbl用别名a代替

WHERE NOT EXISTS (SELECT * FROM dtl_tbl b WHERE a.hdr_key =
b.hdr_key)

2.SELECT a.hdr_key  FROM hdr_tbl a

LEFT JOIN dtl_tbl b ON a.hdr_key = b.hdr_key  WHERE b.hdr_key IS
NULL

3.SELECT hdr_key  FROM hdr_tbl

WHERE hdr_key NOT IN (SELECT hdr_key FROM dtl_tbl)

三种写法都可以得到同样正确的结果,但是效率依次降低。

7、尽量避免在索引过的字符数据中,使用非打头字母搜索。这也使得引擎无法利用索引。

见如下例子:

SELECT * FROM T1 WHERE NAME LIKE ‘%L%’

SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=’L’

SELECT * FROM T1 WHERE NAME LIKE ‘L%’

即使NAME字段建有索引,前两个查询依然无法利用索引完成加快操作,引擎不得不对全表所有数据逐条操作来完成任务。而第三个查询能够使用索引来加快操作。

8、分利用连接条件,在某种情况下,两个表之间可能不只一个的连接条件,这时在
 WHERE 子句中将连接条件完整的写上,有可能大大提高查询速度。

例:

SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO =
B.CARD_NO

SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO
 AND A.ACCOUNT_NO=B.ACCOUNT_NO

第二句将比第一句执行快得多。

9、消除对大型表行数据的顺序存取

尽管在所有的检查列上都有索引,但某些形式的WHERE子句强迫优化器使用顺序存取。如:

SELECT * FROM orders WHERE (customer_num=104  AND order_num>1001)
OR

order_num=1008

解决办法可以使用并集来避免顺序存取:

SELECT * FROM orders WHERE customer_num=104 AND order_num>1001

UNION

SELECT * FROM orders WHERE order_num=1008

这样就能利用索引路径处理查询。

10、避免困难的正规表达式

LIKE关键字支持通配符匹配,技术上叫正规表达式。但这种匹配特别耗费时间。例如:SELECT *
FROM customer WHERE zipcode LIKE “98_ _ _”

即使在zipcode字段上建立了索引,在这种情况下也还是采用顺序扫描的方式。如

果把语句改为SELECT * FROM customer WHERE zipcode >“98000”,在执行查询

时就会利用索引来查询,显然会大大提高速度。

11、 使用视图加速查询

把表的一个子集进行排序并创建视图,有时能加速查询。它有助于避免多重排序

操作,而且在其他方面还能简化优化器的工作。例如:

SELECT cust.name,rcvbles.balance,……other columns

FROM cust,rcvbles

WHERE cust.customer_id = rcvlbes.customer_id

AND rcvblls.balance>0

AND cust.postcode>“98000”

ORDER BY cust.name

如果这个查询要被执行多次而不止一次,可以把所有未付款的客户找出来放在一个

视图中,并按客户的名字进行排序:

CREATE VIEW DBO.V_CUST_RCVLBES

AS

SELECT cust.name,rcvbles.balance,……other columns

FROM cust,rcvbles

WHERE cust.customer_id = rcvlbes.customer_id

AND rcvblls.balance>0

ORDER BY cust.name

然后以下面的方式在视图中查询:

SELECT * FROM  V_CUST_RCVLBES

WHERE postcode>“98000”

视图中的行要比主表中的行少,而且物理顺序就是所要求的顺序,减少了磁盘

I/O,所以查询工作量可以得到大幅减少。

12、能够用BETWEEN的就不要用IN

SELECT * FROM T1 WHERE ID IN (10,11,12,13,14)

改成:

SELECT * FROM T1 WHERE ID BETWEEN 10 AND 14

因为IN会使系统无法使用索引,而只能直接搜索表中的数据。

13、DISTINCT的就不用GROUP BY

SELECT OrderID  FROM Details WHERE UnitPrice
> 10 GROUP BY OrderID

可改为:

SELECT DISTINCT OrderID FROM Details WHERE
UnitPrice > 10

14、部分利用索引

1.SELECT employeeID, firstname, lastname

FROM names

WHERE dept = ‘prod’ or city = ‘Orlando’ or division = ‘food’

2.SELECT employeeID, firstname, lastname FROM names
WHERE dept = ‘prod’

UNION ALL

SELECT employeeID, firstname, lastname FROM names WHERE city = ‘Orlando’

UNION ALL

SELECT employeeID, firstname, lastname FROM names WHERE division = ‘food’

如果dept 列建有索引则查询2可以部分利用索引,查询1则不能。

15、 能用UNION
 ALL就不要用UNION

UNION  ALL不执行SELECT DISTINCT函数,这样就会减少很多不必要的资源

16、不要写一些不做任何事的查询

如:SELECT COL1 FROM T1 WHERE 1=0

SELECT COL1 FROM T1 WHERE COL1=1 AND COL1=2

这类死码不会返回任何结果集,但是会消耗系统资源。

17、 尽量不要用SELECT INTO语句。

SELECT INOT 语句会导致表锁定,阻止其他用户访问该表。

18、 必要时强制查询优化器使用某个索引

SELECT * FROM T1 WHERE nextprocess = 1 AND processid IN
(8,32,45)

改成:

SELECT * FROM T1 (INDEX = IX_ProcessID) WHERE nextprocess = 1 AND processid
IN (8,32,45)

则查询优化器将会强行利用索引IX_ProcessID 执行查询。

19、
虽然UPDATE、DELETE语句的写法基本固定,但是还是对UPDATE语句给点建议:

a)    尽量不要修改主键字段。

b)    当修改VARCHAR型字段时,尽量使用相同长度内容的值代替。

c)    尽量最小化对于含有UPDATE触发器的表的UPDATE操作。

d)    避免UPDATE将要复制到其他数据库的列。

e)    避免UPDATE建有很多索引的列。

f)    避免UPDATE在WHERE子句条件中的列。

时间: 2024-08-27 23:54:03

数据库设计与SQL优化的建议的相关文章

数据库设计与性能优化

转自:http://blog.51cto.com/jimshu/1250066 一.数据库设计与性能优化--概述 jimshu关注2人评论5892人阅读2013-07-16 08:02:14 前言 我1998年第一次接触SQL Server 6.5 for Windows NT 4.0,当时的感觉就认为SQL Server只是一个功能强大的Excel文件.现在回想起来,当年抱着这样一种态度,我开发的那些应用程序应该是非常幼稚的,其性能可想而知.记得那时候随便查询一笔记录就要花费十几秒,已是司空见

大数据量查询优化——数据库设计、SQL语句、JAVA编码

数据库设计方面: 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描.             如: select id from t where num is null              可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from t where num=0 3

高性能可扩展MySQL数据库设计及架构优化 电商项目

第1章 数据库开发规范的制定    俗话说:"没有规矩不成方圆".这一章,我们就先来制定数据库开发的各种规范,包括:数据库命名规范.数据库基本设计规范.数据库索引设计规范.数据库字段设计规范.SQL开发规范以及数据库操作规范.通过这些规范的制定可以指导并规范我们后续的开发工作,为我们以后的工作提供一个良好的基础.... 第2章 电商实例数据库结构设计    数据库开发规范的基础之上,如何更好的利用规范设计出易于维护和伸缩性良好的数据库结构,是我们的学习目的.这一章我们根据常用电商项目需

高性能可扩展MySQL数据库设计及架构优化 电商项目_1

一 数据库设计规范 1 命名规范 所有数据库对象名称必须用小写字母并下划线分割 对象名称禁止使用MySQL保留关键字 命名要做到见名识义,不超过32字节 临时表必须tmp前缀 日期后缀 备份库表bak前缀 日期后缀 所有存储相同数据的列名和类型必须一致 2 数据库基本设计规范 所有表必须用innodb引擎 数据库和表字符集同意使用utf8(全存储中文的可以使用gbk 或是gbk2312) 所有表和字段都使用comment加注释 从一开始就进行数据字典的维护 尽量控制单表数据量的大小 建议500万

数据库设计与SQL查询优化

1.概述   2.数据库设计原则 1)熟悉需求 2)开发符合规范的数据库 3)审核数据库设计 审核组除了要审核数据库设计中的逻辑问题:还要关注数据字典是否详细易懂:数据表结构是否冗余及提出修改建议.  3.数据库设计规范 1)命名规范 2)明确实体和数据表的关系 3)一张数据表不能既没有主键也没有外键 4)基本表特征 5)必须满足第一第二范式,尽量满足第三范式

表设计与SQL优化

1. 说说分区表的主要好处是什么,为什么会有这些好处. 分区功能能够将表.索引或索引组织表进一步细分为段,这些数据库对象的段叫做分区.每个分区有自己的名称,还可以选择自己的存储特性. 从数据库管理员的角度来看,一个分区后的对象具有多个段,这些段既可进行集体管理,也可单独管理,这就使数据库管理员在管理分区后的对象时有相当大的灵活性.但是,从应用程序的角度来看,分区后的表与非分区表完全相同,使用 SQL DML 命令访问分区后的表时,无需任何修改. 对于超级大表来说,分区可以大大提高性能,不仅是操作

[转]Oracle DB 通过SQL 优化管理性能

? 将SQL 优化指导用于: – 确定使用资源最多的 SQL 语句 – 优化使用资源最多的 SQL 语句 ? 使用SQL 访问指导优化工作量 SQL 优化 SQL 优化进程 ? 确定没有很好地优化的SQL 语句. ? 优化各条语句. ? 优化整个应用程序. 一般情况下,效果最明显的优化工作是SQL 优化.没有很好地优化的SQL 会不必要地使用过多资源.这种低效率会降低可伸缩性.使用更多的OS 和数据库资源并增加响应时间.要对没有很好地优化的SQL 语句进行优化,必须先确定这些语句,然后再进行优化

基于oracle的sql优化方法论

Oracle数据库里SQL优化的终极目标就是要缩短目标SQL语句的执行时间.要达到上述目的,我们通常只有如下三种方法可以选择: 1.降低目标SQL语句的资源消耗: 2.并行执行目标SQL语句: 3.平衡系统的资源消耗. "方法1:降低目标SQL语句的资源消耗"以缩短执行时间,这是最常用的SQL优化方法.这种方法的核心是要么通过在不更改业务逻辑的情况下改写SQL来降低目标SQL语句的资源消耗,要么不改SQL但通过调整执行计划或相关表的数据来降低目标SQL语句的资源消耗. 方法2:并行执行

对oracle中SQL优化的理解

Oracle数据库里SQL优化的终极目标就是要缩短目标SQL语句的执行时间.要达到上述目的,我们通常只有如下三种方法可以选择:1.降低目标SQL语句的资源消耗.2.并行执行目标SQL语句.3.平衡系统的资源消耗.方法1:a.在不更改业务逻辑的情况下改写SQL来降低目标SQL语句的资源消耗. b.不改写SQL但通过调整执行计划或相关表的数据来降低目标SQL语句的资源消耗.注意:走索引不一定比全表扫描好,例如在很多情况下走索引的嵌套循环连接的执行效率往往比不上走全表扫描的哈希连接的执行效率.方法2: