七大SQL代码编写原则:可显著提高数据库性能!

理论上,数据库性能调优应由数据库管理员(DBA)完成,但是开发人员有义务书写更规范的SQL代码,这也可以有效提高数据库性能。本文将介绍七大SQL代码编写规范,这是提高数据库性能最简单有效的方法。

1、改进索引

我们创建索引一定是有目的,目的是为了更快的查询。当然,创建有用的索引是获得更优性能的最佳方法之一,有用的索引可以帮助用户查找具有较少I/O操作和资源占用的数据。索引越多意味着SELECT查询可能会更快,因为索引的数据量比全表少,需要扫描的数据相对较少;索引已经对字段排序,可以进行二分法查询。但是,如果我们对每一列都建立索引,需要的额外存储空间就会加大,DML(INSERT,UPDATE和DELETE)操作将显著减慢,因为每个操作都需要维护索引。

因此,如果你的应用程序主要使用SELECT语句,则更多的索引可能会有帮助,但如果主要是DML操作,则需要限制创建的索引数。

你可以在每个表上创建主键,使其成为聚簇索引(请注意,如果在Enterprise Manager中设置主键,则默认情况下将对其进行聚类)。当然,你可以在外键列上创建索引,外键列上缺少索引会带来两个问题——限制并发性和影响性能。

2、删除不必要的索引

索引维护需要大量的CPU和I/O资源,这是开发人员必须要考虑的问题。

例如,MS SQL Server为其用户提供dm_db_index_usage_stats DMV以用于统计索引使用情况。你可以使用以下代码获取不同索引的使用情况,对于未曾使用过或使用频率很低的索引,我们最好删除掉,这样会提高MS SQL Server的性能。


SELECT
OBJECT_NAME(IUS.[OBJECT_ID]) AS [OBJECT NAME],
DB_NAME(IUS.database_id) AS [DATABASE NAME],
I.[NAME] AS [INDEX NAME],
USER_SEEKS,
USER_SCANS,
USER_LOOKUPS,
USER_UPDATES
FROM SYS.DM_DB_INDEX_USAGE_STATS AS IUS
INNER JOIN SYS.INDEXES AS I
ON I.[OBJECT_ID] = IUS.[OBJECT_ID]
AND I.INDEX_ID = IUS.INDEX_ID

(MS SQL Server Performance Monitoring地址:https://www.datasunrise.com/performance_monitoring/ms-sql-server/)

3、避免代码中出现循环

在许多情况下,开发人员可以简化代码来提高性能,比如:


for (int i = 0; i < 1000; i++)
{
    SqlCommand cmd = new SqlCommand(“INSERT INTO TBL (A,B,C) VALUES…”);
    cmd.ExecuteNonQuery();
}

在此示例中,1000个按顺序查询数据库的操作需要占用大量系统资源。但是,通过使用INSERT和UPDATE语句可以很容易地避免这种循环,例如:


INSERT INTO TableName (A,B,C) VALUES (1,2,3),(4,5,6),(7,8,9) — SQL SERVER 2008
INSERT INTO TableName (A,B,C) SELECT 1,2,3 UNION ALL SELECT 4,5,6 — SQL SERVER 2005
UPDATE TableName SET A = CASE B
        WHEN 1 THEN ‘NEW VALUE’
        WHEN 2 THEN ‘NEW VALUE 2’
        WHEN 3 THEN ‘NEW VALUE 3’
    END
WHERE B in (1,2,3)

寻找一切可能的方法来减少到服务器的往返次数,返回多个结果集是执行此操作的一种方法。

4、避免使用相关子查询

相关子查询是使用外部查询中的值的子查询(嵌套在另一个查询中的查询)。相关子查询的执行依赖于外部查询,多数情况下是子查询的WHERE子句中引用外部查询的表。执行过程如下:

(1)从外层查询中取出一个元组,将元组相关列的值传给内层查询。

(2)执行内层查询,得到子查询操作的值。

(3)外查询根据子查询返回的结果或结果集得到满足条件的行。

(4)然后外层查询取出下一个元组重复做步骤1-3,直到外层的元组全部处理完毕。 

例如:


SELECT c.Name,
       c.City,
       (SELECT CompanyName FROM Company WHERE ID = c.CompanyID) AS CompanyName
FROM Customer c

在此示例中,存在问题是一个查询(SELECT c.Name)返回的每一行都调用内部查询(SELECT CompanyName FROM Company WHERE ID = c.CompanyID),这种方式是比较低效的。

开发人员可以使用JOIN构造更高效的查询:


SELECT c.Name,
       c.City,
       co.CompanyName
FROM Customer c
        LEFT JOIN Company co
                ON c.CompanyID = co.CompanyID

5、使用SELECT而不是SELECT *

使用Select *(全选)查询时,你将查询所选表中的所有数据,包括不必要的数据。因此,请仔细定义SELECT查询的范围,避免不必要的操作。

低效示例:


SELECT *FROM public.customers
Efficient:
SELECT FirstName, LastName, Address, ZIPFROM public.customers

6、避免使用SELECT DISTINCT

此查询的工作原理是对查询中的所有字段进行分组以创建不同的结果,虽然这种方法很方便,但它需要大量的系统资源。

反面教材:


SELECT DISTINCT FirstName, LastName, StateFROM public.customers
An efficient and accurate query:
SELECT FirstName, LastName, StateFROM public.customers

注意:仅在短语结尾处使用通配符

搜索纯文本数据时,通配符可帮助开发人员创建最广泛的搜索。但是,这种类型的搜索也是效率最低的搜索。

反面教材:


SELECT City FROM Customers
WHERE City LIKE ‘%Char%’

更有效的查询方式:


SELECT City FROM Customers
WHERE City LIKE ‘Char%’

7、避免建立临时表

避免使用临时表,如果一定要用,请使用Create Table #temp显式创建,也可以使用子查询作为替代。如果你使用SQL语句生成一个巨大的临时表,内存放不下时会全部拷贝到磁盘,IO瞬间飙升。因此,MySQL在执行SQL查询时可能会用到临时表,但是大部分情况下,用到临时表就意味着性能较低。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31077337/viewspace-2158715/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/31077337/viewspace-2158715/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值