索引:

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. JS高级程序设计2

    面向对象 ,基本模式.对象字面量模式.工厂模式.构造函数模式.原型模式.组合构造函数和原型模式.其他模式见电子书:动态原型模式.寄生构造函数模式(不推荐).稳妥构造函数模式(要求安全的环境,不使用ne ...

  2. Java集合源码学习(二)ArrayList

    1.关于ArrayList ArrayList直接继承AbstractList,实现了List. RandomAccess.Cloneable.Serializable接口,为什么叫"Arr ...

  3. Spring MVC 注解

    概述   Spring MVC是一个采用依赖注入的思想编写.对象的依赖注入Bean的方式可以通过Spring XML里面配置,配置之后的Bean使用时候,无需使用New关键字建立对象.但是如果所有的B ...

  4. C语言之指针变量

    菜单导航 1.指针变量 2.指针和数组 3.常量指针和指向常量的指针 4.指针和字符串的关系 5.数组越界造成的访问不属于自己的内存空间现象 6.引用数据类型和基本数据类型,形参和实参 7.字符串和字 ...

  5. 一起学Hive——创建内部表、外部表、分区表和分桶表及导入数据

    Hive本身并不存储数据,而是将数据存储在Hadoop的HDFS中,表名对应HDFS中的目录/文件.根据数据的不同存储方式,将Hive表分为外部表.内部表.分区表和分桶表四种数据模型.每种数据模型各有 ...

  6. mongodb输错命令后不能删除问题

    在用crt连接Linux操作MongoDB时,命令输错了,想删除的时候,却删除不了,原因是crt的配置有问题,解决办法如下 第一步:选项-->会话选项

  7. 执行shell脚本提示“-bash: ./checkP.sh: /bin/sh^M: bad interpreter: No such file or directory”解决方法

    在windows机器下新建了一个shell脚本如下

  8. Jenkins.war包构建Jenkins平台

    [root@jenkins ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo [roo ...

  9. ajax请求后台,response.sendRedirect失效,无法重定向

    今天在写项目的时候,想加一个切换用户,需要清除session并且跳转到登录页面,发起一个ajax请求后,执行完发现无法跳转. 原因在于: (从网上摘录) Ajax只是利用脚本访问对应url获取数据而已 ...

  10. L1-006 连续因子 (20 分) 模拟

    一个正整数 N 的因子中可能存在若干连续的数字.例如 630 可以分解为 3×5×6×7,其中 5.6.7 就是 3 个连续的数字.给定任一正整数 N,要求编写程序求出最长连续因子的个数,并输出最小的 ...