SQL Server的查询优化器在select查询执行的时候产生一个高效的查询执行计划。如果优化器不能选择最优的计划,那么就需要检查查询计划、统计信息、支持的索引等,而通过使用提示可以改变优化器选择查询计划的工程,使优化器生成一个更好的执行计划。
1、联接提示
<join_hint> ::= { LOOP | HASH | MERGE | REMOTE }
- --没有提示的查询
- select *
- from Production.Product p
- innerjoin production.productreview r
- on r.productid = p.productid
- --Loop适合:当一个表很小另一个表很大、在关联的列上有索引时
- select *
- from Production.Product p
- inner loop join production.productreview r
- on r.productid = p.productid
- --merge适合:按照关联列排序的中等或者大的表
- select *
- from Production.Product p
- inner merge join production.productreview r
- on r.productid = p.productid
- --hash适合:没有排序的大的表
- select *
- from Production.Product p
- inner hash join production.productreview r
- on r.productid = p.productid
--没有提示的查询
select *
from Production.Product p
inner join production.productreview r
on r.productid = p.productid
--Loop适合:当一个表很小另一个表很大、在关联的列上有索引时
select *
from Production.Product p
inner loop join production.productreview r
on r.productid = p.productid
--merge适合:按照关联列排序的中等或者大的表
select *
from Production.Product p
inner merge join production.productreview r
on r.productid = p.productid
--hash适合:没有排序的大的表
select *
from Production.Product p
inner hash join production.productreview r
on r.productid = p.productid
2、查询提示与表提示
<query_hint > ::=
{ { HASH | ORDER } GROUP
| { CONCAT | HASH | MERGE } UNION
| { LOOP | MERGE | HASH } JOIN
| EXPAND VIEWS
| FAST number_rows
| FORCE ORDER
| IGNORE_NONCLUSTERED_COLUMNSTORE_INDEX
| KEEP PLAN
| KEEPFIXED PLAN
| MAXDOP number_of_processors
| MAXRECURSION number
| OPTIMIZE FOR ( @variable_name { UNKNOWN | = literal_constant } [ , ...n ] )
| OPTIMIZE FOR UNKNOWN
| PARAMETERIZATION { SIMPLE | FORCED }
| RECOMPILE
| ROBUST PLAN
| USE PLAN N'xml_plan'
| TABLE HINT ( exposed_object_name [ , <table_hint> [ [, ]...n ] ] )
}
<table_hint> ::=
[ NOEXPAND ] {
INDEX ( index_value [ ,...n ] ) | INDEX = ( index_value )
| FORCESEEK [( index_value ( index_column_name [,... ] ) ) ]
| FORCESCAN
| HOLDLOCK
| NOLOCK
| NOWAIT
| PAGLOCK
| READCOMMITTED
| READCOMMITTEDLOCK
| READPAST
| READUNCOMMITTED
| REPEATABLEREAD
| ROWLOCK
| SERIALIZABLE
| SPATIAL_WINDOW_MAX_CELLS = integer
| TABLOCK
| TABLOCKX
| UPDLOCK
| XLOCK
查询提示的参数
指定在查询的 GROUP BY 或 DISTINCT 子句中所说明的聚合应使用哈希或排列。
如果指定了多个 UNION 提示,查询优化器就会从这些指定的提示中选择开销最少的策略。
如果指定了多个联接提示,则优化器从允许的联接策略中选择开销最少的联接策略。
联接提示 (Transact-SQL)
当视图名称由查询文本中的视图定义替换时,视图将展开。
实际上,该查询提示不允许在查询计划中直接使用索引视图和直接在索引视图上使用索引。
FROM。
只有语句的 SELECT 部分中的视图(包括 INSERT、UPDATE、MERGE 和 DELETE 语句中的视图)才受提示影响。
number_rows 后,查询继续执行并生成完整的结果集。
使用 FORCE ORDER 不会影响查询优化器可能的角色逆转行为。
|
|
|---|
|
如果指定 FORCE ORDER,则保留此默认行为。 |
指定 KEEP PLAN 可确保当表有多个更新时不会频繁地对查询进行重新编译。
指定 KEEPFIXED PLAN 可确保仅当更改基础表的架构或在那些表上执行 sp_recompile 时才重新编译查询。
如果查询包含避免使用 columnstore 索引的查询提示以及有关使用 columnstore 索引的索引提示,则这些提示将发生冲突,查询将返回错误。
配置 max degree of parallelism 服务器配置选项。
|
|
|---|
|
如果 MAXDOP 设置为零,服务器将选择最大并行度。 |
如果未指定此选项,则对服务器的默认限制为 100。
当在查询执行期间达到指定或默认的 MAXRECURSION 数量限制时,将结束查询并返回错误。
所返回的任何部分结果都可能无法包括超过指定最大递归级别的递归级别上的所有行。
WITH common_table_expression (Transact-SQL)。
仅在查询优化期间使用该值,在查询执行期间不使用该值。
重新编译存储过程。
OPTIMIZE FOR UNKNOWN指示查询优化器在编译和优化查询时使用所有局部变量的统计数据而不是初始值,包括使用强制参数化创建的参数。
这些值仅用于查询优化期间,而不会用于查询执行期间。
PARAMETERIZATION { SIMPLE | FORCED }指定在编译查询时 SQL Server 查询优化器应用于此查询的参数化规则。
|
|
|---|
|
不能直接在查询中指定该查询提示。 |
使用计划指南指定查询参数化行为。
RECOMPILE在编译查询计划时,RECOMPILE 查询提示将使用查询中任意本地变量的当前值,如果查询位于存储过程中,这些当前值将传递给任意参数。
在创建计划指南时,RECOMPILE 也很有用。
ROBUST PLAN通过使用 ROBUST PLAN,可以指示查询优化器不考虑可能会遇到该问题的所有查询计划。
如果数据库引擎遇到过长的行,则返回执行错误。
USE PLAN N'xml_plan'不能使用 INSERT、UPDATE、MERGE 或 DELETE 语句来指定 USE PLAN。
TABLE HINT (exposed_object_name [, <table_hint> [ [, ]...n] ])计划指南的上下文中将表提示用作查询提示。
exposed_object_name 可以为以下引用之一:
-
exposed_object_name 就是别名。
-
exposed_object_name 就是这个由两部分组成的名称。
请参阅示例 J。
<table_hint> ::= { [ NOEXPAND ] { INDEX ( index_value [ ,...n] ) | INDEX = (index_value ) | FORCESEEK [(index_value(index_column_name [,...])) ]| FORCESCAN | HOLDLOCK | NOLOCK | NOWAIT | PAGLOCK | READCOMMITTED | READCOMMITTEDLOCK | READPAST | READUNCOMMITTED | REPEATABLEREAD | ROWLOCK | SERIALIZABLE |SPATIAL_WINDOW_MAX_CELLS | TABLOCK | TABLOCKX | UPDLOCK | XLOCK }表提示 (Transact-SQL)。
有关详细信息,请参阅备注。
|
|
|---|
|
在未来的版本中,对优化器进行内部修改后可允许考虑更多计划。 |
只有在 INSERT 语句中使用了 SELECT 子句时,才能在该语句中指定查询提示。
exposed_object_name 指定的值必须与该查询或子查询中公开的名称完全匹配。
将表提示指定为查询提示
对于所有其他即席查询,建议仅将这些提示指定为表提示。
如果将 INDEX、FORCESCAN 和 FORCESEEK 表提示指定为查询提示,它们会对以下对象有效:
-
表
-
视图
-
索引视图
-
公用表表达式(必须在其结果集填充公用表表达式的 SELECT 语句中指定提示)
-
动态管理视图
-
命名子查询
当通过使用 OPTION 子句中的 TABLE HINT 指定了非 INDEX、FORCESCAN 或 FORCESEEK 的表提示,而未指定匹配的查询提示时,或指定了后者而未指定前者,则会引发错误 8702,表示 OPTION 子句会导致查询的语义发生变化,该查询将失败。
- declare @a table (v varchar(100),vid int)
- insertinto @a
- select'abc'as v,1 as vid
- unionall
- select'cde',123
- unionall
- select'cd',2
- unionall
- select'abc',12
- unionall
- select'def',123
- unionall
- select'cde',12
- unionall
- select'def',2
- unionall
- select'cde',1
- unionall
- select'cdef',1
- --1.group
- --1.1hash
- select v,
- COUNT(vid)
- from @a
- groupby v
- option(hash group)
- --1.2order
- select v,
- COUNT(vid)
- from @a
- groupby v
- option(ordergroup)
- --1.3可以用在distinct中
- selectdistinct *
- from @a
- option(ordergroup)
- --2.union
- --2.1hash
- select'abc'as v,1 as vid
- union
- select'cd',123
- union
- select'cd',2
- union
- select'abc',1
- option(hash union)
- --2.2merge
- select'abc'as v,1 as vid
- union
- select'cd',123
- union
- select'cd',2
- union
- select'abc',1
- option(merge union)
- --2.3concat
- select'abc'as v,1 as vid
- union
- select'cd',123
- union
- select'cd',2
- union
- select'abc',1
- option(concat union)
- --3.join
- --3.1hash
- select *
- from
- (
- select'abc'as v,1 as vid
- unionall
- select'cd',2
- )a
- innerjoin
- (
- select'cd'as v,2 as vid
- unionall
- select'abc',1
- )b
- on a.vid = b.vid
- option(hash join)
- --3.2merge
- select *
- from
- (
- select'abc'as v,1 as vid
- unionall
- select'cd',2
- )a
- innerjoin
- (
- select'cd'as v,2 as vid
- unionall
- select'abc',1
- )b
- on a.vid = b.vid
- option(merge join)
- --3.3loop
- select *
- from
- (
- select'abc'as v,1 as vid
- unionall
- select'cd',2
- )a
- innerjoin
- (
- select'cd'as v,2 as vid
- unionall
- select'abc',1
- )b
- on a.vid = b.vid
- option(loop join)
- --4.expand views
- --建表
- select * into wc_objects
- from sys.objects
- --添加主键约束
- altertable wc_objects
- addconstraint pk_wc_objectid primarykey(object_id)
- --创建视图
- createview select_wc_objects
- with schemabinding
- as
- selectname,
- object_id,
- type,
- type_desc
- from dbo.wc_objects
- go
- --创建唯一的聚集索引作为视图索引(也就是视图对应的索引)
- createunique clustered index uni_select_wc_objects
- on select_wc_objects(object_id)
- --这里会展开视图,直接引用底层的原始表wc_objects
- select *
- from select_wc_objects
- --不会展开,直接使用唯一聚集索引uni_select_wc_objects中的数据
- select *
- from select_wc_objects with(noexpand)
- --5.fast n:对查询进行优化,以便快速检索前n行
- select o.OrderDate,
- o.SalesOrderNumber
- from sales.SalesOrderHeader o
- innerjoin sales.SalesOrderDetail d
- on o.SalesOrderID =d.SalesOrderID
- option(fast 100) --在返回前n行后,查询继续执行并生成完整的结果集
- --6.force order:一般不建议使用,应该由SQL Server来决定联接顺序
- SELECT *
- FROM sales.SalesOrderHeader o
- INNERJOIN sales.SalesOrderDetail m
- ON O.salesorderid = m.salesorderid
- innerjoin production.Product e
- on m.ProductID = e.ProductID
- option(forceorder) --用了这个导致查询更慢
- --7.keep plan:强制查询优化器对查询放宽估计的重新编译阈值
- SELECT *
- FROM sales.SalesOrderHeader o
- INNERJOIN sales.SalesOrderDetail m
- ON O.salesorderid = m.salesorderid
- innerjoin production.Product e
- on m.ProductID = e.ProductID
- option(keep plan)
- --8.keepfixed plan:强制查询优化器不因统计信息的更改而重新编译查询
- --可确保只有更改基础表的架构或在那些表上执行sp_recompile时才重新编译查询
- SELECT *
- FROM sales.SalesOrderHeader o
- INNERJOIN sales.SalesOrderDetail m
- ON O.salesorderid = m.salesorderid
- innerjoin production.Product e
- on m.ProductID = e.ProductID
- option(keepfixed plan)
- /*=================================
- 9.maxrecursion自动产生大量连续的数字
- ==================================*/
- WITH t
- AS
- (
- SELECT 1 AS r
- UNIONALL
- SELECT r+1
- FROM t
- WHERE r < 10000
- )
- SELECT *
- FROM t
- OPTION(maxrecursion 10000) --限制最大递归数字
- --10.MAXDOP
- --对于指定了max degree of parallelism配置选项的查询,
- --会覆盖sp_configure 和资源调控器的该选项
- SELECT *
- FROM sales.SalesOrderHeader o
- INNERJOIN sales.SalesOrderDetail m
- ON O.salesorderid = m.salesorderid
- innerjoin production.Product e
- on m.ProductID = e.ProductID
- option(maxdop 2)
- --11.OPTIMIZE FOR
- declare @name nvarchar(50)
- declare @id int
- select @name ='a',
- @id =500
- SELECT *
- FROM sales.SalesOrderHeader o
- INNERJOIN sales.SalesOrderDetail m
- ON O.salesorderid = m.salesorderid
- innerjoin production.Product e
- on m.ProductID = e.ProductID
- where e.Namelike @name +'%'
- and e.ProductID >= @id
- option(optimize for(@name='a',@id unknown))
- --12.OPTIMIZE FOR UNKNOWN
- declare @name1 nvarchar(50)
- declare @id1 int
- select @name1 ='a',
- @id1 =500;
- SELECT *
- FROM sales.SalesOrderHeader o
- INNERJOIN sales.SalesOrderDetail m
- ON O.salesorderid = m.salesorderid
- innerjoin production.Product e
- on m.ProductID = e.ProductID
- where e.Namelike @name1 +'%'
- and e.ProductID >= @id1
- option(optimize for unknown)
- --12.use plan
- createtable txt(id numeric(10,0) primarykey,
- v varchar(20),
- vv int )
- createindex txt_v on txt(v)
- insertinto txt
- select object_id,
- type_desc,
- schema_id
- from sys.objects
- where LEN(type_desc) < 20
- --取得xml格式的执行计划
- setstatistics xml on
- select *
- from txt
- where id > 1000 and
- vv > 2
- setstatistics xml off
- select *
- from txt
- option(
- use plan
- '<ShowPlanXML xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan"
- Version="1.1" Build="10.50.1600.1">
- <BatchSequence><Batch><Statements>
- <StmtSimple StatementText="SELECT * FROM [txt] WHERE [id]>@1 AND [vv]>@2"
- StatementId="1" StatementCompId="1" StatementType="SELECT" StatementSubTreeCost="0.00429444"
- StatementEstRows="42.2945" StatementOptmLevel="TRIVIAL" QueryHash="0xA4E0AA4B0A87F88B"
- QueryPlanHash="0x3325250D8A42F500">
- <StatementSetOptions QUOTED_IDENTIFIER="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true"
- ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" NUMERIC_ROUNDABORT="false"/>
- <QueryPlan DegreeOfParallelism="1" CachedPlanSize="16" CompileTime="1" CompileCPU="1"
- CompileMemory="136"><RelOp NodeId="0"
- PhysicalOp="Clustered Index Seek" LogicalOp="Clustered Index Seek"
- EstimateRows="42.2945" EstimateIO="0.00386574" EstimateCPU="0.0004287"
- AvgRowSize="34" EstimatedTotalSubtreeCost="0.00429444"
- TableCardinality="292" Parallel="0" EstimateRebinds="0" EstimateRewinds="0">
- <OutputList><ColumnReference Database="[test2]"
- Schema="[dbo]"Table="[txt]"Column="id"/><ColumnReference
- Database="[test2]"Schema="[dbo]"Table="[txt]"Column="v"/>
- <ColumnReference Database="[test2]"Schema="[dbo]"Table="[txt]"Column="vv"/>
- </OutputList><RunTimeInformation><RunTimeCountersPerThread Thread="0"
- ActualRows="5" ActualEndOfScans="1" ActualExecutions="1"/>
- </RunTimeInformation><IndexScan Ordered="1" ScanDirection="FORWARD"
- ForcedIndex="0" ForceSeek="0" NoExpandHint="0"><DefinedValues>
- <DefinedValue><ColumnReference Database="[test2]"
- Schema="[dbo]"Table="[txt]"Column="id"/>
- </DefinedValue><DefinedValue><ColumnReference
- Database="[test2]"Schema="[dbo]"Table="[txt]"
- Column="v"/></DefinedValue><DefinedValue>
- <ColumnReference Database="[test2]"Schema="[dbo]"
- Table="[txt]"Column="vv"/></DefinedValue></DefinedValues>
- <Object Database="[test2]"Schema="[dbo]"Table="[txt]"
- Index="[PK__txt__3213E83F4D1564AE]" IndexKind="Clustered"/>
- <SeekPredicates><SeekPredicateNew><SeekKeys>
- <StartRange ScanType="GT"><RangeColumns>
- <ColumnReference Database="[test2]"Schema="[dbo]"Table="[txt]"
- Column="id"/></RangeColumns><RangeExpressions><ScalarOperator
- ScalarString="CONVERT_IMPLICIT(numeric(10,0),[@1],0)"><Identifier>
- <ColumnReference Column="ConstExpr1003"><ScalarOperator>
- <Convert DataType="numeric"Precision="10" Scale="0" Style="0" Implicit="1">
- <ScalarOperator><Identifier><ColumnReference Column="@1"/>
- </Identifier></ScalarOperator></Convert></ScalarOperator>
- </ColumnReference></Identifier></ScalarOperator>
- </RangeExpressions></StartRange></SeekKeys></SeekPredicateNew>
- </SeekPredicates><Predicate><ScalarOperator
- ScalarString="[test2].[dbo].[txt].[vv]>CONVERT_IMPLICIT(int,[@2],0)"><Compare CompareOp="GT">
- <ScalarOperator><Identifier><ColumnReference Database="[test2]"Schema="[dbo]"
- Table="[txt]"Column="vv"/></Identifier></ScalarOperator><ScalarOperator>
- <Identifier><ColumnReference Column="ConstExpr1004"><ScalarOperator>
- <Convert DataType="int" Style="0" Implicit="1"><ScalarOperator>
- <Identifier><ColumnReference Column="@2"/></Identifier>
- </ScalarOperator></Convert></ScalarOperator></ColumnReference>
- </Identifier></ScalarOperator></Compare></ScalarOperator>
- </Predicate></IndexScan></RelOp><ParameterList>
- <ColumnReference Column="@2" ParameterCompiledValue="(2)" ParameterRuntimeValue="(2)"/>
- <ColumnReference Column="@1" ParameterCompiledValue="(1000)"
- ParameterRuntimeValue="(1000)"/></ParameterList></QueryPlan>
- </StmtSimple></Statements></Batch></BatchSequence></ShowPlanXML>')
- --14.PARAMETERIZATION { SIMPLE | FORCED }
- --PARAMETERIZATION查询提示只能在计划指南中指定,不能直接在查询中指定该查询提示
- --14.1运行多条类似的查询
- select * from txt where id = 8
- select * from txt where id = 9
- --14.2通过查询缓存的计划所对应的sql文本,发现很多都是相同的
- --而且大部分的objtype都是proc,adhoc,prepared.
- SELECT *
- FROM SYS.dm_exec_cached_plans E
- CROSS APPLY SYS.dm_exec_sql_text(E.plan_handle)EE
- WHERE EE.text LIKE'%select * from txt where id =%'
- declare @sqltext nvarchar(max)
- declare @parameter nvarchar(max)
- --14.3获取查询的参数化形式以及查询的参数,放入变量中
- exec sp_get_query_template
- @querytext = N'select * from txt where id = 8',
- @templatetext= @sqltext output,
- @parameters = @parameter output
- --14.4使用模板来创建计划指南
- exec sp_create_plan_guide
- @name = 'plan_guide_txt_template',
- @stmt = @sqltext,
- @type = 'template',
- @module_or_batch = null,
- @params = @parameter,
- @hints = 'option(parameterization forced)'
- --14.5再次查询发现多条执行计划已经变为一条,usecounts计数增加
- SELECT *
- FROM SYS.dm_exec_cached_plans E
- CROSS APPLY SYS.dm_exec_sql_text(E.plan_handle)EE
- WHERE EE.text LIKE'%select * from txt where id =%'
- --15.ROBUST PLAN
- --查询优化器尝试一个计划,该计划可能以性能为代价获得最大可能的行大小
- SELECT *
- FROM sales.SalesOrderHeader o
- INNERJOIN sales.SalesOrderDetail m
- ON O.salesorderid = m.salesorderid
- innerjoin production.Product e
- on m.ProductID = e.ProductID
- option(ROBUST PLAN)
- --16.RECOMPILE
- SELECT *
- FROM sales.SalesOrderHeader o
- INNERJOIN sales.SalesOrderDetail m
- ON O.salesorderid = m.salesorderid
- innerjoin production.Product e
- on m.ProductID = e.ProductID
- option(recompile)
- --如果是存储过程,可以通过下面的方式来显式的重新编译
- exec 存储过程名称 with recompile
declare @a table (v varchar(100),vid int)
insert into @a
select 'abc' as v,1 as vid
union all
select 'cde',123
union all
select 'cd',2
union all
select 'abc',12
union all
select 'def',123
union all
select 'cde',12
union all
select 'def',2
union all
select 'cde',1
union all
select 'cdef',1
--1.group
--1.1hash
select v,
COUNT(vid)
from @a
group by v
option(hash group)
--1.2order
select v,
COUNT(vid)
from @a
group by v
option(order group)
--1.3可以用在distinct中
select distinct *
from @a
option(order group)
--2.union
--2.1hash
select 'abc' as v,1 as vid
union
select 'cd',123
union
select 'cd',2
union
select 'abc',1
option(hash union)
--2.2merge
select 'abc' as v,1 as vid
union
select 'cd',123
union
select 'cd',2
union
select 'abc',1
option(merge union)
--2.3concat
select 'abc' as v,1 as vid
union
select 'cd',123
union
select 'cd',2
union
select 'abc',1
option(concat union)
--3.join
--3.1hash
select *
from
(
select 'abc' as v,1 as vid
union all
select 'cd',2
)a
inner join
(
select 'cd' as v,2 as vid
union all
select 'abc',1
)b
on a.vid = b.vid
option(hash join)
--3.2merge
select *
from
(
select 'abc' as v,1 as vid
union all
select 'cd',2
)a
inner join
(
select 'cd' as v,2 as vid
union all
select 'abc',1
)b
on a.vid = b.vid
option(merge join)
--3.3loop
select *
from
(
select 'abc' as v,1 as vid
union all
select 'cd',2
)a
inner join
(
select 'cd' as v,2 as vid
union all
select 'abc',1
)b
on a.vid = b.vid
option(loop join)
--4.expand views
--建表
select * into wc_objects
from sys.objects
--添加主键约束
alter table wc_objects
add constraint pk_wc_objectid primary key(object_id)
--创建视图
create view select_wc_objects
with schemabinding
as
select name,
object_id,
type,
type_desc
from dbo.wc_objects
go
--创建唯一的聚集索引作为视图索引(也就是视图对应的索引)
create unique clustered index uni_select_wc_objects
on select_wc_objects(object_id)
--这里会展开视图,直接引用底层的原始表wc_objects
select *
from select_wc_objects
--不会展开,直接使用唯一聚集索引uni_select_wc_objects中的数据
select *
from select_wc_objects with(noexpand)
--5.fast n:对查询进行优化,以便快速检索前n行
select o.OrderDate,
o.SalesOrderNumber
from sales.SalesOrderHeader o
inner join sales.SalesOrderDetail d
on o.SalesOrderID =d.SalesOrderID
option(fast 100) --在返回前n行后,查询继续执行并生成完整的结果集
--6.force order:一般不建议使用,应该由SQL Server来决定联接顺序
SELECT *
FROM sales.SalesOrderHeader o
INNER JOIN sales.SalesOrderDetail m
ON O.salesorderid = m.salesorderid
inner join production.Product e
on m.ProductID = e.ProductID
option(force order) --用了这个导致查询更慢
--7.keep plan:强制查询优化器对查询放宽估计的重新编译阈值
SELECT *
FROM sales.SalesOrderHeader o
INNER JOIN sales.SalesOrderDetail m
ON O.salesorderid = m.salesorderid
inner join production.Product e
on m.ProductID = e.ProductID
option(keep plan)
--8.keepfixed plan:强制查询优化器不因统计信息的更改而重新编译查询
--可确保只有更改基础表的架构或在那些表上执行sp_recompile时才重新编译查询
SELECT *
FROM sales.SalesOrderHeader o
INNER JOIN sales.SalesOrderDetail m
ON O.salesorderid = m.salesorderid
inner join production.Product e
on m.ProductID = e.ProductID
option(keepfixed plan)
/*=================================
9.maxrecursion自动产生大量连续的数字
==================================*/
WITH t
AS
(
SELECT 1 AS r
UNION ALL
SELECT r+1
FROM t
WHERE r < 10000
)
SELECT *
FROM t
OPTION(maxrecursion 10000) --限制最大递归数字
--10.MAXDOP
--对于指定了max degree of parallelism配置选项的查询,
--会覆盖sp_configure 和资源调控器的该选项
SELECT *
FROM sales.SalesOrderHeader o
INNER JOIN sales.SalesOrderDetail m
ON O.salesorderid = m.salesorderid
inner join production.Product e
on m.ProductID = e.ProductID
option(maxdop 2)
--11.OPTIMIZE FOR
declare @name nvarchar(50)
declare @id int
select @name ='a',
@id =500
SELECT *
FROM sales.SalesOrderHeader o
INNER JOIN sales.SalesOrderDetail m
ON O.salesorderid = m.salesorderid
inner join production.Product e
on m.ProductID = e.ProductID
where e.Name like @name +'%'
and e.ProductID >= @id
option(optimize for(@name='a',@id unknown))
--12.OPTIMIZE FOR UNKNOWN
declare @name1 nvarchar(50)
declare @id1 int
select @name1 ='a',
@id1 =500;
SELECT *
FROM sales.SalesOrderHeader o
INNER JOIN sales.SalesOrderDetail m
ON O.salesorderid = m.salesorderid
inner join production.Product e
on m.ProductID = e.ProductID
where e.Name like @name1 +'%'
and e.ProductID >= @id1
option(optimize for unknown)
--12.use plan
create table txt(id numeric(10,0) primary key,
v varchar(20),
vv int )
create index txt_v on txt(v)
insert into txt
select object_id,
type_desc,
schema_id
from sys.objects
where LEN(type_desc) < 20
--取得xml格式的执行计划
set statistics xml on
select *
from txt
where id > 1000 and
vv > 2
set statistics xml off
select *
from txt
option(
use plan
'<ShowPlanXML xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan"
Version="1.1" Build="10.50.1600.1">
<BatchSequence><Batch><Statements>
<StmtSimple StatementText="SELECT * FROM [txt] WHERE [id]>@1 AND [vv]>@2"
StatementId="1" StatementCompId="1" StatementType="SELECT" StatementSubTreeCost="0.00429444"
StatementEstRows="42.2945" StatementOptmLevel="TRIVIAL" QueryHash="0xA4E0AA4B0A87F88B"
QueryPlanHash="0x3325250D8A42F500">
<StatementSetOptions QUOTED_IDENTIFIER="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true"
ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" NUMERIC_ROUNDABORT="false"/>
<QueryPlan DegreeOfParallelism="1" CachedPlanSize="16" CompileTime="1" CompileCPU="1"
CompileMemory="136"><RelOp NodeId="0"
PhysicalOp="Clustered Index Seek" LogicalOp="Clustered Index Seek"
EstimateRows="42.2945" EstimateIO="0.00386574" EstimateCPU="0.0004287"
AvgRowSize="34" EstimatedTotalSubtreeCost="0.00429444"
TableCardinality="292" Parallel="0" EstimateRebinds="0" EstimateRewinds="0">
<OutputList><ColumnReference Database="[test2]"
Schema="[dbo]" Table="[txt]" Column="id"/><ColumnReference
Database="[test2]" Schema="[dbo]" Table="[txt]" Column="v"/>
<ColumnReference Database="[test2]" Schema="[dbo]" Table="[txt]" Column="vv"/>
</OutputList><RunTimeInformation><RunTimeCountersPerThread Thread="0"
ActualRows="5" ActualEndOfScans="1" ActualExecutions="1"/>
</RunTimeInformation><IndexScan Ordered="1" ScanDirection="FORWARD"
ForcedIndex="0" ForceSeek="0" NoExpandHint="0"><DefinedValues>
<DefinedValue><ColumnReference Database="[test2]"
Schema="[dbo]" Table="[txt]" Column="id"/>
</DefinedValue><DefinedValue><ColumnReference
Database="[test2]" Schema="[dbo]" Table="[txt]"
Column="v"/></DefinedValue><DefinedValue>
<ColumnReference Database="[test2]" Schema="[dbo]"
Table="[txt]" Column="vv"/></DefinedValue></DefinedValues>
<Object Database="[test2]" Schema="[dbo]" Table="[txt]"
Index="[PK__txt__3213E83F4D1564AE]" IndexKind="Clustered"/>
<SeekPredicates><SeekPredicateNew><SeekKeys>
<StartRange ScanType="GT"><RangeColumns>
<ColumnReference Database="[test2]" Schema="[dbo]" Table="[txt]"
Column="id"/></RangeColumns><RangeExpressions><ScalarOperator
ScalarString="CONVERT_IMPLICIT(numeric(10,0),[@1],0)"><Identifier>
<ColumnReference Column="ConstExpr1003"><ScalarOperator>
<Convert DataType="numeric" Precision="10" Scale="0" Style="0" Implicit="1">
<ScalarOperator><Identifier><ColumnReference Column="@1"/>
</Identifier></ScalarOperator></Convert></ScalarOperator>
</ColumnReference></Identifier></ScalarOperator>
</RangeExpressions></StartRange></SeekKeys></SeekPredicateNew>
</SeekPredicates><Predicate><ScalarOperator
ScalarString="[test2].[dbo].[txt].[vv]>CONVERT_IMPLICIT(int,[@2],0)"><Compare CompareOp="GT">
<ScalarOperator><Identifier><ColumnReference Database="[test2]" Schema="[dbo]"
Table="[txt]" Column="vv"/></Identifier></ScalarOperator><ScalarOperator>
<Identifier><ColumnReference Column="ConstExpr1004"><ScalarOperator>
<Convert DataType="int" Style="0" Implicit="1"><ScalarOperator>
<Identifier><ColumnReference Column="@2"/></Identifier>
</ScalarOperator></Convert></ScalarOperator></ColumnReference>
</Identifier></ScalarOperator></Compare></ScalarOperator>
</Predicate></IndexScan></RelOp><ParameterList>
<ColumnReference Column="@2" ParameterCompiledValue="(2)" ParameterRuntimeValue="(2)"/>
<ColumnReference Column="@1" ParameterCompiledValue="(1000)"
ParameterRuntimeValue="(1000)"/></ParameterList></QueryPlan>
</StmtSimple></Statements></Batch></BatchSequence></ShowPlanXML>')
--14.PARAMETERIZATION { SIMPLE | FORCED }
--PARAMETERIZATION查询提示只能在计划指南中指定,不能直接在查询中指定该查询提示
--14.1运行多条类似的查询
select * from txt where id = 8
select * from txt where id = 9
--14.2通过查询缓存的计划所对应的sql文本,发现很多都是相同的
--而且大部分的objtype都是proc,adhoc,prepared.
SELECT *
FROM SYS.dm_exec_cached_plans E
CROSS APPLY SYS.dm_exec_sql_text(E.plan_handle)EE
WHERE EE.text LIKE '%select * from txt where id =%'
declare @sqltext nvarchar(max)
declare @parameter nvarchar(max)
--14.3获取查询的参数化形式以及查询的参数,放入变量中
exec sp_get_query_template
@querytext = N'select * from txt where id = 8',
@templatetext= @sqltext output,
@parameters = @parameter output
--14.4使用模板来创建计划指南
exec sp_create_plan_guide
@name = 'plan_guide_txt_template',
@stmt = @sqltext,
@type = 'template',
@module_or_batch = null,
@params = @parameter,
@hints = 'option(parameterization forced)'
--14.5再次查询发现多条执行计划已经变为一条,usecounts计数增加
SELECT *
FROM SYS.dm_exec_cached_plans E
CROSS APPLY SYS.dm_exec_sql_text(E.plan_handle)EE
WHERE EE.text LIKE '%select * from txt where id =%'
--15.ROBUST PLAN
--查询优化器尝试一个计划,该计划可能以性能为代价获得最大可能的行大小
SELECT *
FROM sales.SalesOrderHeader o
INNER JOIN sales.SalesOrderDetail m
ON O.salesorderid = m.salesorderid
inner join production.Product e
on m.ProductID = e.ProductID
option(ROBUST PLAN)
--16.RECOMPILE
SELECT *
FROM sales.SalesOrderHeader o
INNER JOIN sales.SalesOrderDetail m
ON O.salesorderid = m.salesorderid
inner join production.Product e
on m.ProductID = e.ProductID
option(recompile)
--如果是存储过程,可以通过下面的方式来显式的重新编译
exec 存储过程名称 with recompile
表提示的参数
指定表提示时必须使用括号。
|
|
|---|
|
不推荐省略 WITH 关键字:后续版本的 Microsoft SQL Server 将删除该功能。请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。 |
例如:
如果指定的提示含其他选项,则指定的提示必须含 WITH 关键字:
建议在表提示之间使用逗号。
|
|
|---|
|
不推荐用空格而不是逗号分隔提示:后续版本的 Microsoft SQL Server 将删除该功能。请不要在新的开发工作中使用该功能,并尽快修改当前还在使用该功能的应用程序。 |
在针对兼容级别为 90 及更高的数据库的查询中使用提示时,即存在这些限制。
有关详细信息,请参阅备注。
只能为每个表指定一个索引提示。
如果不存在聚集索引,则 INDEX(0) 强制执行表扫描,INDEX(1) 被解释为错误。
如果提示索引的集合并未包含查询引用的所有列,则会在 SQL Server 数据库引擎检索所有索引列后执行提取操作以检索其余列。
|
|
|---|
|
另外,不允许对包含指定索引提示的表执行索引 OR 操作。 |
表提示中的最大索引数为 250 个非聚集索引。
OPENROWSET
如果不指定 KEEPIDENTITY,则将验证但不导入此列的标识值。查询优化器将根据创建表时指定的种子值和增量值自动分配唯一值。
|
|
|---|
|
如果成功跳过了一个标识列,则查询优化器自动将标识列的唯一值分配到导入的表行中。 |
大容量导入数据时保留标识值 (SQL Server)。
DBCC CHECKIDENT (Transact-SQL)。
OPENROWSET 一起使用时)。
指定数据记录在某一表列缺少值时插入此列的默认值(如果有),而不是插入 NULL。
在大容量导入期间保留空值或使用默认值 (SQL Server)。
在这种情况下,查询优化器仅考虑通过指定的索引(至少使用指定的索引列)执行索引查找操作。
可以通过以下方式指定 FORCESEEK 提示。
|
语法 |
示例 |
说明 |
|---|---|---|
|
没有索引或 INDEX 提示 |
FROM dbo.MyTable WITH (FORCESEEK) |
查询优化器仅考虑执行索引查找操作以通过任意相关索引访问表或视图。 |
|
与 INDEX 提示组合使用 |
FROM dbo.MyTable WITH (FORCESEEK, INDEX (MyIndex)) |
查询优化器仅考虑执行索引查找操作以通过指定的索引访问表或视图。 |
|
通过指定索引和索引列进行参数化 |
FROM dbo.MyTable WITH (FORCESEEK (MyIndex (col1, col2, col3))) |
查询优化器仅考虑执行索引查找操作,以通过指定的索引(至少使用指定的索引列)访问表或视图。 |
使用 FORCESEEK 提示(具有或不带索引参数)时,考虑以下准则。
-
查询提示 (Transact-SQL)。
-
若要将 FORCESEEK 应用到索引视图,还必须指定 NOEXPAND 提示。
-
对每个表或视图最多应用该提示一次。
-
带索引提示指定 FORCESEEK 时,将返回错误 7377;不带索引提示使用 FORCESEEK 时,将返回错误 8180。
-
如果 FORCESEEK 导致找不到计划,将返回错误 8622。
使用索引参数指定 FORCESEEK 时,遵循以下准则和限制。
-
该提示不能与 INDEX 提示或另一个 FORCESEEK 提示一起指定。
-
至少必须指定一个列且该列为第一个键列。
-
FORCESEEK (MyIndex (a, c)。
-
在提示中指定的列名顺序必须与引用的索引中列的顺序匹配。
-
不能指定自动包含在索引中的聚集键列,但是优化器可以使用这些列。
-
返回错误 366。
-
修改索引定义(例如通过添加或删除列)可能需要修改引用该索引的查询。
-
该提示阻止优化器考虑表的任何空间或 XML 索引。
-
该提示不能与 FORCESCAN 提示一起指定。
-
对于分区的索引,不能在 FORCESEEK 提示中指定 SQL Server 隐式添加的分区列。
|
|
|---|
|
在未来的版本中,对优化器进行内部修改后可允许考虑更多计划。 |
出现这样的情况时,授予该操作的内存量太小,查询性能将受影响。
可以带索引提示 INDEX(0) 指定 FORCESCAN,以强制对基表执行表扫描操作。
这意味着扫描仅适用于剩余分区而非整个表。
FORCESCAN 提示存在以下限制。
-
不能为作为 INSERT、UPDATE 或 DELETE 语句的目标的表指定该提示。
-
该提示不能与一个以上的索引提示一起使用。
-
该提示阻止优化器考虑表的任何空间或 XML 索引。
-
不能为远程数据源指定该提示。
-
该提示不能与 FORCESEEK 提示一起指定。
HOLDLOCK 不能被用于包含 FOR BROWSE 选项的 SELECT 语句。
IGNORE_CONSTRAINTSOPENROWSET 一起使用时)。
注意,您无法禁用 UNIQUE、PRIMARY KEY 或 NOT NULL 约束。
通过禁用 CHECK 和 FOREIGN KEY 约束,可以导入数据,然后使用 Transact-SQL 语句清除该数据。
如果在大容量导入操作之前表不为空,则重新验证约束的开销可能超过对增量数据应用 CHECK 和 FOREIGN KEY 约束的开销。
IGNORE_TRIGGERSOPENROWSET 一起使用时)。
默认情况下,INSERT 将应用触发器。
仅当应用程序不依赖任何触发器,并且必须最大程度地提高性能时,才使用 IGNORE_TRIGGERS。
NOLOCK有关详细信息,请参阅本主题后面的 READUNCOMMITTED。
|
|
|---|
|
对于 UPDATE 或 DELETE 语句:后续版本的 Microsoft SQL Server 将删除该功能。请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。 |
NOWAIT 等同于将特定表的 SET LOCK_TIMEOUT 值指定为 0。
PAGLOCK在从 SNAPSHOT 隔离级别操作的事务中指定时,除非将 PAGLOCK 与需要锁的其他表提示(例如,UPDLOCK 和 HOLDLOCK)组合,否则不会取得页锁。
READCOMMITTEDSET TRANSACTION ISOLATION LEVEL (Transact-SQL)。
|
|
|---|
|
对于 UPDATE 或 DELETE 语句:后续版本的 Microsoft SQL Server 将删除该功能。请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。 |
不能对 INSERT 语句的目标表指定此提示;将返回错误 4140。
READPAST使用 READPAST 的队列读取器会跳过被其他事务锁定的队列项,跳至下一个可用的队列项,而不是等待其他事务释放锁。
读取外键或索引视图或者修改辅助索引时,使用 READPAST 的更新或删除操作可能发生阻塞。
在从 SNAPSHOT 隔离级别操作的事务中指定时,READPAST 必须与需要锁的其他表提示(例如,UPDLOCK 和 HOLDLOCK)组合。
当 READ_COMMITTED_SNAPSHOT 数据库选项设置为 ON 并且满足以下条件之一时,无法指定 READPAST 表提示。
-
会话的事务隔离级别为 READ COMMITTED。
-
查询中也指定了 READCOMMITTED 表提示。
若要在上述情况下指定 READPAST 提示,请删除 READCOMMITTED 表提示(如果存在),然后在查询中包括 READCOMMITTEDLOCK 表提示。
READUNCOMMITTED这可能会使您的事务出错,向用户显示从未提交过的数据,或者导致用户两次看到记录(或根本看不到记录)。
相反,持有 Sch-S 锁的查询将阻塞尝试获取 Sch-M 锁的并发事务。
SQL Server 查询优化器忽略 FROM 子句中应用于 UPDATE 或 DELETE 语句的目标表的 READUNCOMMITTED 和 NOLOCK 提示。
|
|
|---|
|
请避免在新的开发工作上下文中使用这些提示,并计划修改当前使用它们的应用程序。 |
可以通过使用以下任意一种方法,在保护事务避免对未提交的数据修改进行脏读的同时最大程度地减少锁争用:
-
READ COMMITTED 隔离级别,其中 READ_COMMITTED_SNAPSHOT 数据库选项设置为 ON。
-
SNAPSHOT 隔离级别。
SET TRANSACTION ISOLATION LEVEL (Transact-SQL)。
|
|
|---|
|
如果在指定了 READUNCOMMITTED 的情况下收到 601 号错误消息,则按解决死锁错误 (1205) 的方法解决该错误,然后重试语句。 |
SET TRANSACTION ISOLATION LEVEL (Transact-SQL)。
ROWLOCK如果在 SNAPSHOT 隔离级别运行的事务中指定了行锁,除非将 ROWLOCK 与需要锁的其他表提示(例如,UPDLOCK 和 HOLDLOCK)组合使用,否则不会采用行锁。
SPATIAL_WINDOW_MAX_CELLS = integernumber 是 1 到 8192 之间的值。
对于较稀疏的数据,较小的数字将减少主要筛选器执行时间。
此选项适用于手动和自动网格分割。
SERIALIZABLESET TRANSACTION ISOLATION LEVEL (Transact-SQL)。
TABLOCK如果同时指定了 HOLDLOCK,则会一直持有表锁,直至事务结束。
INSERT (Transact-SQL)。
在大容量导入中按最小方式记录日志的前提条件。
TABLOCKX指定对表采用排他锁。
UPDLOCK如果将 UPDLOCK 与 TABLOCK 组合使用或出于一些其他原因采用表级锁,将采用排他 (X) 锁。
例如,如果将会话的隔离级别设置为 SERIALIZABLE 且查询指定 (UPDLOCK, READCOMMITTED),则忽略 READCOMMITTED 提示且使用 SERIALIZABLE 隔离级别运行事务。
XLOCK如果同时指定了 ROWLOCK, PAGLOCK 或 TABLOCK,则排他锁将应用于相应的粒度级别。
在后一种情况中,使用 OPTION (EXPAND VIEWS) 查询提示可阻止访问索引视图。
另外,SQL Server 还将执行对应的锁一致性检查。
例如,如果表具有非聚集索引,而且由涵盖索引处理使用锁提示的 SELECT 语句,则获得的锁针对的是涵盖索引中的索引键,而不是基表中的数据行。
表达式和函数引用的表在被访问时将不使用 NOLOCK 表提示。
对于 FROM 子句中的每个表,SQL Server 不允许存在多个来自以下各个组的表提示:
-
粒度提示:PAGLOCK、NOLOCK、READCOMMITTEDLOCK、ROWLOCK、TABLOCK 或 TABLOCKX。
-
隔离级别提示:HOLDLOCK、NOLOCK、READCOMMITTED、REPEATABLEREAD 和 SERIALIZABLE。
筛选索引提示
创建筛选索引。
USE AdventureWorks2012;
GO
IF EXISTS (SELECT name FROM sys.indexes
WHERE name = N'FIBillOfMaterialsWithComponentID'
AND object_id = OBJECT_ID(N'Production.BillOfMaterials'))
DROP INDEX FIBillOfMaterialsWithComponentID
ON Production.BillOfMaterials;
GO
CREATE NONCLUSTERED INDEX "FIBillOfMaterialsWithComponentID"
ON Production.BillOfMaterials (ComponentID, StartDate, EndDate)
WHERE ComponentID IN (533, 324, 753);
GO
SELECT StartDate, ComponentID FROM Production.BillOfMaterials
WITH( INDEX (FIBillOfMaterialsWithComponentID) )
WHERE ComponentID in (533, 324, 753, 855, 924);
GO
CREATE INDEX (Transact-SQL)。
使用 NOEXPAND
SQL Server 2012 各个版本支持的功能 (http://go.microsoft.com/fwlink/?linkid=232473)。
但是,为了使优化器考虑使用索引视图进行匹配,或者使用通过 NOEXPAND 提示引用的索引视图,则必须将以下 SET 选项设置为 ON。
|
ANSI_NULLS |
ANSI_WARNINGS |
CONCAT_NULL_YIELDS_NULL |
|
ANSI_PADDING |
1 |
QUOTED_IDENTIFIERS |
因此,不必手动调整此设置。
另外,必须将 NUMERIC_ROUNDABORT 选项设置为 OFF。
如果某个查询没有在 FROM 子句中直接命名特定索引视图,则 SQL Server 不提供用于在此查询中强制使用此视图的提示;但是,即使查询中未直接引用索引视图,查询优化器仍会考虑使用索引视图。
将表提示用作查询提示
查询提示 (Transact-SQL)。
- --1.index
- SELECT *
- FROM sales.SalesOrderHeader o with(index(PK_SalesOrderHeader_SalesOrderID))
- INNERJOIN sales.SalesOrderDetail m with(index(0)) --聚集索引扫描
- ON O.salesorderid = m.salesorderid
- innerjoin production.Product e with (index(1)) --聚集索引扫描或查找
- on m.ProductID = e.ProductID
- --2.KEEPIDENTITY
- --建表
- createtable dbo.y(yearvarchar(4) primarykey)
- insertinto dbo.y
- values('2010'),
- ('2011')
- CREATETABLE dbo.CALENDAR
- (
- ID NUMERIC (10) identity(1,1) NOTNULL,
- YEAR VARCHAR (4) NULL referencesforeignkey y(year),
- QUARTER VARCHAR (1) NULLdefault datename(quarter,getdate()),
- MONTH VARCHAR (2) NULL,
- WEEK VARCHAR (2) NULL,
- WEEK_MONTH VARCHAR (2) NULL,
- WORK_DAY BITNULL,
- IS_HOLIDAY BITNULL,
- CONSTRAINT PK_CALENDAR PRIMARYKEY (ID)
- )
- insertinto dbo.calendar with(keepidentity)
- (ID,
- YEAR,
- QUARTER,
- MONTH,
- WEEK,
- WEEK_MONTH,
- WORK_DAY,
- IS_HOLIDAY
- )
- select *
- from
- openrowset(bulk 'c:\calendar.txt', --要读取的文件路径和名称
- formatfile='c:\calendar.fmt', --格式化文件的路径和名称
- firstrow = 1, --要载入的第一行
- --lastrow = 1000, --要载入的最后一行,此值必须大于firstrow
- maxerrors = 10, --在加载失败之前加载操作中最大的错误数
- errorfile ='c:\calendar_error.txt', --存放错误的文件
- rows_per_batch = 100 --每个批处理导入的行数
- ) as calendar
- --3.KEEPDEFAULTS
- insertinto dbo.MDM_CALENDAR with(keepdefaults)
- ( ID ,
- YEAR ,
- CAL_QUARTER ,
- CAL_MONTH ,
- CAL_WEEK ,
- CAL_WEEK_OF_MONTH ,
- CAL_DAY ,
- CAL_DATE ,
- HOLIDAY
- )
- select *
- from
- openrowset(bulk 'c:\calendar.txt', --要读取的文件路径和名称
- formatfile='c:\calendar.fmt', --格式化文件的路径和名称
- firstrow = 1, --要载入的第一行
- --lastrow = 1000, --要载入的最后一行,此值必须大于firstrow
- maxerrors = 10, --在加载失败之前加载操作中最大的错误数
- errorfile ='c:\calendar_error.txt', --存放错误的文件
- rows_per_batch = 100 --每个批处理导入的行数
- ) as calendar
- --4.IGNORE_CONSTRAINTS
- --无法禁用:UNIQUE、PRIMARY KEY 或 NOT NULL约束
- --可以禁用:CHECK 和 FOREIGN KEY 约束
- insertinto dbo.CALENDAR with(ignore_constraints)
- ( ID,
- YEAR,
- QUARTER,
- MONTH,
- WEEK,
- WEEK_MONTH,
- WORK_DAY,
- IS_HOLIDAY
- )
- select *
- from
- openrowset(bulk 'c:\calendar.txt', --要读取的文件路径和名称
- formatfile='c:\calendar.fmt', --格式化文件的路径和名称
- firstrow = 1, --要载入的第一行
- --lastrow = 1000, --要载入的最后一行,此值必须大于firstrow
- maxerrors = 10, --在加载失败之前加载操作中最大的错误数
- errorfile ='c:\calendar_error.txt', --存放错误的文件
- rows_per_batch = 100 --每个批处理导入的行数
- ) as calendar
- --5.IGNORE_TRIGGERS
- --建立触发器
- createtrigger dbo.calendar_trigger
- on dbo.calendar
- afterinsert
- as
- begin
- select * from inserted
- end
- go
- insertinto dbo.CALENDAR with(ignore_triggers,ignore_constraints)
- (ID,
- YEAR,
- QUARTER,
- MONTH,
- WEEK,
- WEEK_MONTH,
- WORK_DAY,
- IS_HOLIDAY
- )
- select *
- from
- openrowset(bulk 'c:\calendar.txt', --要读取的文件路径和名称
- formatfile='c:\calendar.fmt', --格式化文件的路径和名称
- firstrow = 1, --要载入的第一行
- --lastrow = 1000, --要载入的最后一行,此值必须大于firstrow
- maxerrors = 10, --在加载失败之前加载操作中最大的错误数
- errorfile ='c:\calendar_error.txt', --存放错误的文件
- rows_per_batch = 100 --每个批处理导入的行数
- ) as calendar
- --6.forceseek
- SELECT *
- FROM sales.SalesOrderHeader o with(forceseek)
- INNERJOIN sales.SalesOrderDetail m with(forceseek,
- index(IX_SalesOrderDetail_ProductID))
- ON O.salesorderid = m.salesorderid
- innerjoin production.Product e
- --with(FORCESEEK (PK_Product_ProductID (col1, col2, col3))) 这样用法在SQL Server2012的
- on m.ProductID = e.ProductID
- --7.forcescan:在SQL Server2012中引入的,在SQL Server2008不可用
- SELECT *
- FROM sales.SalesOrderHeader o with(FORCESCAN)
- INNERJOIN sales.SalesOrderDetail m with(forcescan,
- index(IX_SalesOrderDetail_ProductID))
- ON O.salesorderid = m.salesorderid
- innerjoin production.Product e
- with(forcescan (PK_Product_ProductID (col1, col2, col3)))
- on m.ProductID = e.ProductID
- /*=============================================
- 8.锁定提示
- 锁粒度:
- ROWLOCK
- PAGLOCK
- TABLOCK(在堆上的delete语句中加上tablock后,在行被删除时回收分页)
- 锁模式:
- READPAST:不读取被锁定的记录
- NOWAIT(SET LOCK_TIMEOUT 0):锁等待时间为0,也就是如果需要的数据被锁定,那么返回错误
- UPDLOCK:更新锁
- XLOCK:独占锁
- TABLOCKX = TABLOCK + XLOCK
- 隔离级别:
- READUNCOMMITTED/NOLOCK
- READCOMMITTED
- READCOMMITTEDLOCK:无论数据库是否设置了快照选项,读取时都会获取共享锁
- REPEATABLEREAD
- SERIALIZABLE/HOLDLOCK
- ===============================================*/
- begin tran
- SELECT *
- FROM Production.Product WITH(holdlock)
- select *
- from sys.dm_tran_locks
- where request_session_id = @@SPID
- commit tran