索引:

set  statistics io on
select p.productID,p.name,p.Weight,p.StandardCost from production.product p
where p.productID = 738 create index testPro_In on production.product(StandardCost)
/*大量的行返回使得非聚集索引,要用覆盖索引
不需要增加索引中列的数量或索引键的大小,因为所包含的列只保存在索引的叶子级别上。
include最好在以下情况使用:
1.不希望增加索引键的大小,但是仍然希望有一个覆盖索引
2.你打算索引一种不能被索引的数据类型(除了文本、ntext和图像)
3.你已经超过了一个索引的关键字列的最大数量
*/
SELECT TOP 1000
[CardNumber]
,[ExpMonth]
,[ExpYear]
FROM [AdventureWorks].[Sales].[CreditCard] cc
where cc.[ExpMonth] between 6 and 9
and cc.[ExpYear] = 2008
order by cc.[ExpMonth] drop index [Sales].[CreditCard].ix_test
--如果无include([CardNumber]),则逻辑读取 189次,有则逻辑读取 21 次
--注意创建索引的列的顺序先[ExpMonth],后[ExpYear]
create nonclustered index ix_test on [AdventureWorks].[Sales].[CreditCard](
[ExpMonth],[ExpYear]
)include([CardNumber]) SELECT
[CardNumber]
,[ExpMonth]
,[ExpYear]
FROM [AdventureWorks].[Sales].[CreditCard] cc
where cc.[CardNumber]=''
/*覆盖索引*/
select PostalCode from Person.Address where StateProvinceID=42 --drop index Person.Address. create nonclustered index IX_Address_StateProvinceID on Person.Address(StateProvinceID asc)
include(PostalCode)
with(drop_existing=on)
/*
索引交叉
可以再一个表上开发多个索引,然后使用一个连接算法来在两个子集中得到索引交叉
*/
--没有使用列SalesPersonID上的非聚集索引
select * from Sales.SalesOrderHeader
where SalesPersonID=276
and OrderDate between '4/1/2002' and '7/1/2002'
--OrderDate上的非聚集索引
create nonclustered index ix_testsa on Sales.SalesOrderHeader(OrderDate)
--在创建OrderDate上的非聚集索引后,sql使用2个非聚集索引进行索引查找(非扫描) /*
过滤索引
*/
--表 'SalesOrderHeader'。扫描计数 1,逻辑读取 686 次,物理读取 0 次
select OrderDate,ShipDate from Sales.SalesOrderHeader
where PurchaseOrderNumber like 'PO5%'
and SalesPersonID is not null
--表 'SalesOrderHeader'。扫描计数 1,逻辑读取 5 次,物理读取 0 次,
--create nonclustered index ix_test on Sales.SalesOrderHeader(PurchaseOrderNumber,SalesPersonID)
--include(OrderDate,ShipDate)
drop index Sales.SalesOrderHeader.ix_test create nonclustered index ix_test
on Sales.SalesOrderHeader(PurchaseOrderNumber,SalesPersonID)
include(OrderDate,ShipDate)
where PurchaseOrderNumber is not null
and SalesPersonID is not null dbcc show_statistics('[Sales].[SalesOrderDetail]',IX_SalesOrderDetail_ProductID2)
--drop index [Sales].[SalesOrderDetail].[IX_SalesOrderDetail_ProductID2]

  CREATE NONCLUSTERED INDEX [IX_SalesOrderDetail_ProductID2]
ON [Sales].[SalesOrderDetail] ([ProductID])
include([UnitPrice],[ModifiedDate]) set statistics io on
select p.PurchaseOrderID,p.VendorID,p.OrderDate
from Purchasing.PurchaseOrderHeader p
where p.VendorID = 85
and p.OrderDate < '12/5/2003' create nonclustered index ix_test on Purchasing.PurchaseOrderHeader
(OrderDate)
--开启更新统计
alter database AdventureWorks set auto_update_statistics on
/*
密度=1/列中不同值的数量
密度越低,越适合非聚集索引
select 1.0/count(distinct c1) from t1
*/
select 1.0/count(distinct VendorID) from Purchasing.PurchaseOrderHeader select * from sys.dm_db_index_physical_stats(db_id('CI-DNP02'),object_id('t1'),null,null,'sampled')
/*
avg_fragmentation_in_percent--表示索引和堆的逻辑平均碎片百分比,如是堆表且模式为samplyed,
则该值为NULL。如大于40%,可能要重建索引。
fragment_count--表示碎片的数量,或者组成索引和堆的单独页面组数。
page_count--组成统计的索引或数据页面数量的计数。
*/
select * from sys.dm_exec_cached_plans
 /*
EXEC sp_executesql的运用: 此示例存储过程将动态生成并执行 INSERT 语句,以便向正确的表中插入新订单。
此示例使用订货日期生成应包含数据的表的名称,然后将此名称并入 INSERT 语句中
在该过程中使用 sp_executesql 比使用 EXECUTE 执行字符串更有效。
使用 sp_executesql 时,只生成 12 个版本的 INSERT 字符串,每个月的表对应 1 个字符串。
使用 EXECUTE 时,因为参数值不同,每个 INSERT 字符串均是唯一的。
尽管两种方法生成的批处理数相同,但由于 sp_executesql 生成的 INSERT 字符串类似,
因此,查询优化器更有可能重复使用执行计划。
*/
CREATE PROCEDURE InsertSales @PrmOrderID INT, @PrmCustomerID INT,
@PrmOrderDate DATETIME, @PrmDeliveryDate DATETIME
AS
DECLARE @InsertString NVARCHAR(500)
DECLARE @OrderMonth INT -- Build the INSERT statement.
SET @InsertString = 'INSERT INTO ' +
/* Build the name of the table. */
SUBSTRING( DATENAME(mm, @PrmOrderDate), 1, 3) +
CAST(DATEPART(yy, @PrmOrderDate) AS CHAR(4) ) +
'Sales' +
/* Build a VALUES clause. */
' VALUES (@InsOrderID, @InsCustID, @InsOrdDate,' +
' @InsOrdMonth, @InsDelDate)' /* Set the value to use for the order month because
functions are not allowed in the sp_executesql parameter
list. */
SET @OrderMonth = DATEPART(mm, @PrmOrderDate) EXEC sp_executesql @InsertString,
N'@InsOrderID INT, @InsCustID INT, @InsOrdDate DATETIME,
@InsOrdMonth INT, @InsDelDate DATETIME',
@PrmOrderID, @PrmCustomerID, @PrmOrderDate,
@OrderMonth, @PrmDeliveryDate GO
DECLARE @SQLString nvarchar(500);
DECLARE @ParmDefinition nvarchar(500);
DECLARE @SalesOrderNumber nvarchar(25);
DECLARE @IntVariable int;
SET @SQLString = N'SELECT @SalesOrderOUT = MAX(SalesOrderNumber)
FROM Sales.SalesOrderHeader
WHERE CustomerID = @CustomerID';
SET @ParmDefinition = N'@CustomerID int,
@SalesOrderOUT nvarchar(25) OUTPUT';
SET @IntVariable = 22276;
EXECUTE sp_executesql
@SQLString
,@ParmDefinition
,@CustomerID = @IntVariable
,@SalesOrderOUT = @SalesOrderNumber OUTPUT;
-- This SELECT statement returns the value of the OUTPUT parameter.
SELECT @SalesOrderNumber;
-- This SELECT statement uses the value of the OUTPUT parameter in
-- the WHERE clause.
SELECT OrderDate, TotalDue
FROM Sales.SalesOrderHeader
WHERE SalesOrderNumber = @SalesOrderNumber;
/*
引起pro重新编译的情况:
1.由于常规表引起的重新编译
2.由于局部临时表引起的重新编译
*/
IF(SELECT OBJECT_ID('dbo.p1')) IS NOT NULL
DROP PROC dbo.p1;
GO
CREATE PROC dbo.p1
AS
CREATE TABLE dbo.p1_t1(c1 INT); --Ensure table doesn't exist
SELECT * FROM dbo.p1_t1; --Causes recompilation,因为该pro中的表以前不存在,则
--计划不会包含引用该表的select语句的处理策略,因此为了执行select语句,该pro必须重新编译
DROP TABLE dbo.p1_t1;
GO EXEC dbo.p1; --First execution
EXEC dbo.p1; --Second execution --
IF(SELECT OBJECT_ID('dbo.p1')) IS NOT NULL
DROP PROC dbo.p1;
GO
CREATE PROC dbo.p1
AS
CREATE TABLE #p1_t1(c1 INT); --指定本地临时表
SELECT * FROM #p1_t1; --第一次执行时导致重新编译
DROP TABLE #p1_t1;--可选的,因为局部临时表在pro执行结束时自动卸载,这里是为良好的习惯卸载临时表
GO EXEC dbo.p1; --First execution
EXEC dbo.p1; --Second execution,注意,第二次执行时,没有被重新编译 /*
避免引起pro重新编译的情况:
1.不要交替使用ddl和dml语句
2.统计变化引起的
3.使用表变量,表变量特点:1.没有事物日志开销,2.没有锁开销,3.没有回滚开销,4.因为没统计,所以数据量不能大。
4.避免在pro中修改set选项
*/
IF (SELECT OBJECT_ID('dbo.spTempTable')
) IS NOT NULL
DROP PROC dbo.spTempTable
GO
CREATE PROC dbo.spTempTable
AS
CREATE TABLE #MyTempTable (ID INT, Dsc NVARCHAR(50))
INSERT INTO #MyTempTable (
ID,
Dsc
) SELECT ProductModelId, [Name]
FROM Production.ProductModel AS pm; --Needs 1st recompilation
SELECT * FROM #MyTempTable AS mtt; --Needs 2nd recompile
CREATE CLUSTERED INDEX iTest ON #MyTempTable (ID);
SELECT *
FROM #MyTempTable AS mtt; --Needs 3rd recompilation
CREATE TABLE #t2 (c1 INT);
SELECT *
FROM #t2;
--Needs 4th recompilation
GO EXEC spTempTable --First execution,一次执行该pro,被编译4次
/*
1.如果可以,就用between替换in/or,可进一步使用>=,<=的组合代替between
2.使用like替换substring
*/
SELECT d.Name
FROM HumanResources.Department AS d
WHERE SUBSTRING(d.[Name], 1, 1) = 'F' SELECT d.Name
FROM HumanResources.Department AS d
WHERE d.[Name] LIKE 'F%' --查找月份的方案:
SELECT soh.SalesOrderID
,soh.OrderDate
FROM Sales.SalesOrderHeader AS soh
JOIN Sales.SalesOrderDetail AS sod
ON soh.SalesOrderID = sod.SalesOrderID
--WHERE soh.OrderDate >= '2002-04-01' AND soh.OrderDate < '2002-05-01' --good action
WHERE DATEPART(yy, soh.OrderDate) = 2002
AND DATEPART(mm, soh.OrderDate) = 4--bad action SELECT p.FirstName
FROM Person.Person AS p
WHERE p.FirstName < 'B'
OR p.Firstname >= 'C'; SELECT p.MiddleName
FROM Person.Person AS p
WHERE p.MiddleName < 'B'
OR p.MiddleName >= 'C'
OR p.MiddleName IS NULL; CREATE INDEX IX_Test1 ON Person.Person (MiddleName);
CREATE INDEX IX_test2 ON Person.Person (FirstName); DROP INDEX person.Person.ix_test2
DROP INDEX Person.Person.IX_Test1
/*
使用exists代替count(*)验证数据存在
*/
DECLARE @n INT
SELECT @n = COUNT(*)
FROM Sales.SalesOrderDetail AS sod
WHERE sod.OrderQty = 1
IF @n > 0
PRINT 'Record Exists' IF EXISTS ( SELECT sod.*
FROM Sales.SalesOrderDetail AS sod
WHERE sod.OrderQty = 1 )
PRINT 'Record Exists' /*
union 从最终的结果集删除重复并且在每个查询上有效的运行distinct,如允许有重复,则用union all 代替
*/
/*
执行批或存储过程时,在批或存储过程中的每个查询执行之后,服务器报告所影响的行数。
可如下解决:
set nocount on
<sql queries>
set nocount off
*/

锁:

begin tran
delete from dbo.DatabaseLog where DatabaseLogID = 20
select * from sys.dm_tran_locks
rollback select object_name(N'') /*
下面的select语句获取的(s)锁不会保存到事务结束。在默认隔离级别read_committed 之下,
数据被select语句读出后(s)锁立即被释放。
*/
begin tran
select * from Production.Product where productID = 1
--其他查询
commit
/*
更新(u)模式,update:先(u)锁,后(x)锁。update执行中,只可(select)读,(u)锁阻止其他的update
insert,delete 执行开始就获取(x)锁。insert,delete执行中,所有的action都被阻止。
*/
BEGIN TRAN
--1. Read data to be modified using (S)lock instead of (U)lock.
-- Retain the (S)lock using REPEATABLEREAD locking hint,使用REPEATABLEREAD锁提示保持(s)锁
-- since the original (U)lock is retained until the conversion
-- to (X)lock.此后,原来的(u)锁被保持到转换为(x)锁
SELECT *
FROM t1 WITH (REPEATABLEREAD)
WHERE c1 = 1; --Allow another equivalent update action to start concurrently
--允许另一个等价的更新操作并发开始
WAITFOR DELAY '00:00:10'; --2. Modify the data by acquiring(获取) (X)lock
UPDATE t1 WITH (XLOCK)
SET c2 = GETDATE()
WHERE c1 = 1;
COMMIT /*
当一个select语句需要在获取数据后锁住该行数据,防被修改,可使用如下:
*/
begin tran
select * from Production.Product where productID = 1 with(updlock)--(u)锁,也可with(xlock)
--其他查询
commit

sql 2008 查询性能优化笔记的更多相关文章

  1. SQL SERVER 查询性能优化——分析事务与锁(五)

    SQL SERVER 查询性能优化——分析事务与锁(一) SQL SERVER 查询性能优化——分析事务与锁(二) SQL SERVER 查询性能优化——分析事务与锁(三) 上接SQL SERVER ...

  2. SQL Server 查询性能优化 相关文章

    来自: SQL Server 查询性能优化——堆表.碎片与索引(一) SQL Server 查询性能优化——堆表.碎片与索引(二) SQL Server 查询性能优化——覆盖索引(一) SQL Ser ...

  3. Sql Server查询性能优化之走出索引的误区

    据了解绝大多数开发人员对于索引的理解都是一知半解,局限于大多数日常工作没有机会.也什么没有必要去关心.了解索引,实在哪天某个查询太慢了找到查询条件建个索引就ok,哪天又有个查询慢了,再建立个索引就是, ...

  4. SQL Server查询性能优化——堆表、碎片与索引(二)

    本文是对 SQL Server查询性能优化——堆表.碎片与索引(一)的一些总结.  第一:先对 SQL Server查询性能优化——堆表.碎片与索引(一)中的例一的SET STATISTICS IO之 ...

  5. SQL Server查询性能优化——覆盖索引(二)

    在SQL Server 查询性能优化——覆盖索引(一)中讲了覆盖索引的一些理论. 本文将具体讲一下使用不同索引对查询性能的影响. 下面通过实例,来查看不同的索引结构,如聚集索引.非聚集索引.组合索引等 ...

  6. SET STATISTICS IO和SET STATISTICS TIME 在SQL Server查询性能优化中的作用

    近段时间以来,一直在探究SQL Server查询性能的问题,当然也漫无目的的查找了很多资料,也从网上的大神们的文章中学到了很多,在这里,向各位大神致敬.正是受大神们无私奉献精神的影响,所以小弟也作为回 ...

  7. SQl语句查询性能优化

    [摘要]本文从DBMS的查询优化器对SQL查询语句进行性能优化的角度出发,结合数据库理论,从查询表达式及其多种查询条件组合对数据库查询性能优化进行分析,总结出多种提高数据库查询性能优化策略,介绍索引的 ...

  8. Sql Server查询性能优化之不可小觑的书签查找

    小小程序猿SQL Server认知的成长 1.没毕业或工作没多久,只知道有数据库.SQL这么个东东,浑然分不清SQL和Sql Server Oracle.MySql的关系,通常认为SQL就是SQL S ...

  9. SQL Server 查询性能优化——覆盖索引

    覆盖索引又可以称为索引覆盖. 解释一: 就是select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖. 解释二: 索引是高效找到行的一个方法,当能通过检索索引 ...

随机推荐

  1. Dapper Helper

    using System; using System.Collections.Generic; using System.Configuration; using System.Data; using ...

  2. python全栈开发day59-Django基础

    一.今日内容总结 1.HTTP协议: 请求:浏览器发给服务端的消息 格式: 请求方法 URL 协议版本\r\n k1: v1\r\n k2: v2\r\n \r\n 请求体(请求数据) 响应:服务端返 ...

  3. bash: cannot create temp file for here-document: Read-only file system

    文件系统被强制只读问题,第一眼看到百度了一下,说可能磁盘坏了.卧槽我都吓懵了系统盘坏了,闹着玩呢,然后接着查资料,排查 mount 查看所有挂载,发现根目录的挂载权限是ro只读. /dev/sda2 ...

  4. windows 设置开机启动,启动项

    第一步ctrl+R输入以下任意一个 方法一: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp 方法二: shell:start ...

  5. 51Nod1317 相似字符串对 容斥原理 动态规划

    原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1317.html 题目传送门 - 51Nod1317 题意 称一对字符串(A,B)是相似的,当且仅当满 ...

  6. POJ1273 USACO 4.2.1 Drainage Ditches CodeVS1993草地排水 网络流 最大流 SAP

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 传送门 - POJ 传送门 - CodeVS 题意概括 给出一个图,告诉你边和容量,起点是1,汇点是n,让你求最大流. 题解 ...

  7. 启动tomcat出现Removing obsolete files from server... Could not clean server of obsolete ……错误

    在Eclipse启动tomcat出现"Removing obsolete files from server... Could not clean server of obsolete …… ...

  8. 012 pandas与matplotlib结合制图

    这里以后再补充. 1.折线图

  9. 050 Kafka的引入介绍

    高吞吐量的分布式订阅消息系统 1.官网 http://kafka.apache.org/ 2.官网的介绍 3.结构 这个是版本1.0之后的版本. In Kafka the communication ...

  10. Python线程同步

    线程执行 join与setDaemon 子线程在主线程运行结束后,会继续执行完,如果给子线程设置为守护线程(setDaemon=True),主线程运行结束子线程即结束: 如果join()线程,那么主线 ...