DB 性能优化

1. 建立“适当”的索引
微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引、簇集索引)和非聚集索引(nonclustered index,也称非聚类索引、非簇集索引)。下面,我们举例来说明一下聚集索引和非聚集索引的区别:
  • 聚集索引:我们的汉语字典的正文本身就是一个聚集索引。比如,我们要查“安”字,就会很自然地翻开字典的前几页,因为“安”的拼音是“an”,而按照拼 音排序汉字的字典是以英文字母“a”开头并以“z”结尾的,那么“安”字就自然地排在字典的前部。如果您翻完了所有以“a”开头的部分仍然找不到这个字, 那么就说明您的字典中没有这个字;同样的,如果查“张”字,那您也会将您的字典翻到最后部分,因为“张”的拼音是“zhang”。也就是说,字典的正文部 分本身就是一个目录,您不需要再去查其他目录来找到您需要找的内容。我们把这种正文内容本身就是一种按照一定规则排列的目录称为“聚集索引”。
  • 非聚集索引:如果您认识某个字,您可以快速地从自动中查到这个字。但您也可能会遇到您不认识的字,不知道它的发音,这时候,您就不能按照刚才的方法找到您要查的 字,而需要去根据“偏旁部首”查到您要找的字,然后根据这个字后的页码直接翻到某页来找到您要找的字。但您结合“部首目录”和“检字表”而查到的字的排序 并不是真正的正文的排序方法,比如您查“张”字,我们可以看到在查部首之后的检字表中“张”的页码是672页,检字表中“张”的上面是“驰”字,但页码却 是63页,“张”的下面是“弩”字,页面是390页。很显然,这些字并不是真正的分别位于“张”字的上下方,现在您看到的连续的“驰、张、弩”三字实际上 就是他们在非聚集索引中的排序,是字典正文中的字在非聚集索引中的映射。我们可以通过这种方式来找到您所需要的字,但它需要两个过程,先找到目录中的结 果,然后再翻到您所需要的页码。我们把这种目录纯粹是目录,正文纯粹是正文的排序方式称为“非聚集索引

建立原则:

  • 索引应该建立在条件,排序,分组,表联接属性等操作所涉及的列上。
  • 近可能建立在重复数据少的列上。 

索引失效:

  • 避免对索引字段进行计算操作。
  • 避免在索引字段上使用not,<>,!=。
  • 避免在索引列上使用IS NULL和IS NOT NULL。
  • 避免在索引列上出现数据类型转换。
  • 避免在索引字段上使用函数。
  • 避免建立索引的列中使用空值。

提高查询效率的几个注意点:

  • 在可以使用UNION ALL的语句里,使用了UNION。
  • 在WHERE 语句中,尽量避免对索引字段进行计算操作。
2. 改善SQL语句
  • 选择表中行数:SELECT COUNT(*) FROM TableName   
    优化方案:SELECT rows FROM sysindexes WHERE id=OBJECT_ID('TableName') AND indid<2
  • IN适合于外表大而内表小的情况,EXISTS适合于外表小而内表大的情况。

3. 参数化查询

  • 可以防止SQL注入
  • 可以提高查询性能(主要是可以复用查询计划),这点在数据量较大时尤为重要
  • 参数化查询参数类型为可变长度时(varchar,nvarchar,char等)请指定参数类型及长度,若为值类型(int,bigint,decimal,datetime等)则仅指定参数类型即可
  • 传值为varchar(max)或者nvarchar(max)时,参数长度指定为-1即可

4. 检查SQL阻塞原因  

select blocking_session_id, wait_duration_ms, session_id
from sys.dm_os_waiting_tasks
where blocking_session_id is not null

 5. 检查前10个等待资源的SQL语句  

select top 10 *
from sys.dm_os_wait_stats
order by wait_time_ms desc

6. 查询显示 CPU 平均占用率最高的前50个SQL 语句

SELECT TOP 50 total_worker_time/execution_count AS [Avg CPU Time],
(SELECT SUBSTRING(text,statement_start_offset/2,(CASE WHEN      statement_end_offset = -1 then LEN(CONVERT(nvarchar(max), text)) * 2 ELSE statement_end_offset end -statement_start_offset)/2) FROM sys.dm_exec_sql_text(sql_handle)) AS query_text, *
FROM sys.dm_exec_query_stats
ORDER BY [Avg CPU Time] DESC

7. CPU 瓶颈通常由以下原因引起:查询计划并非最优、配置不当、设计因素不良或硬件资源不足。下面的常用查询可帮助您确定导致CPU瓶颈的原因。下面的查询使您能够深入了解当前缓存的哪些批处理或过程占用了大部分CPU资源。  

SELECT TOP 50
SUM(qs.total_worker_time) AS total_cpu_time,
SUM(qs.execution_count) AS total_execution_count,
COUNT(*) AS  number_of_statements,
qs.sql_handle
FROM sys.dm_exec_query_stats AS qs
GROUP BY qs.sql_handle
ORDER BY SUM(qs.total_worker_time) DESC

8. 下面的查询显示缓存计划所占用的CPU总使用率(带 SQL 文本)。  

SELECT
total_cpu_time,
total_execution_count,
number_of_statements,
s2.text
ROM
(SELECT TOP 50
SUM(qs.total_worker_time) AS total_cpu_time,
SUM(qs.execution_count) AS total_execution_count,
COUNT(*) AS  number_of_statements,
qs.sql_handle
FROM
sys.dm_exec_query_stats AS qs
GROUP BY qs.sql_handle
ORDER BY SUM(qs.total_worker_time) DESC) AS stats
CROSS APPLY sys.dm_exec_sql_text(stats.sql_handle) AS s2

9. 下面的示例查询显示已重新编译的前 25 个存储过程。plan_generation_num 指示该查询已重新编译的次数。  

select top 25
sql_text.text,
sql_handle,
plan_generation_num,
execution_count,
dbid,
objectid
from sys.dm_exec_query_stats a
cross apply sys.dm_exec_sql_text(sql_handle) as sql_text
where plan_generation_num > 1
order by plan_generation_num desc

10. 效率较低的查询计划可能增大 CPU 占用率。下面的查询显示哪个查询占用了最多的 CPU 累计使用率  

SELECT
highest_cpu_queries.plan_handle, highest_cpu_queries.total_worker_time, q.dbid, q.objectid, q.number, q.encrypted, q.[text]
from
(select top 50 qs.plan_handle,  qs.total_worker_time from sys.dm_exec_query_stats qs  order by qs.total_worker_time desc) as highest_cpu_queries
cross apply sys.dm_exec_sql_text(plan_handle) as q
order by highest_cpu_queries.total_worker_time desc

11. 下面的查询显示一些可能占用大量 CPU 使用率的运算符(例如 ‘%Hash Match%’、‘%Sort%’)以找出可疑对象。  

select *
from
sys.dm_exec_cached_plans
cross apply sys.dm_exec_query_plan(plan_handle)
where
cast(query_plan as nvarchar(max)) like '%Sort%'
or cast(query_plan as nvarchar(max)) like '%Hash Match%'

12. 如果已检测到效率低下并导致 CPU 占用率较高的查询计划,请对该查询中涉及的表运行 UPDATE STATISTICS 以查看该问题是否仍然存在。然后,收集相关数据并将此问题报告给 PerformancePoint Planning 支持人员。如果您的系统存在过多的编译和重新编译,可能会导致系统出现与 CPU 相关的性能问题。您可以运行下面的 DMV 查询来找出过多的编译/重新编译。  

select * from sys.dm_exec_query_optimizer_info
where counter = 'optimizations' or counter = 'elapsed time'

  

引自:http://www.cnblogs.com/lzrabbit/tag/Sql%20Server/
引自:http://www.cnblogs.com/MR_ke/archive/2010/08/25/1807856.html

原文地址:https://www.cnblogs.com/raysbo/p/2160936.html