【sql】sql一些摘要

--1、临时表(DECLARE @details Table())

DECLARE @details Table(DTaskDetailsId [uniqueidentifier] NOT NULL,--任务id
    DAdvertCompanyFloorId [uniqueidentifier]  NOT NULL,--楼盘id
    DFloorDiscName [nvarchar](100) NOT NULL,--楼盘名
    DAdvertCompanyPointId [uniqueidentifier]  NOT NULL,--点位id
    DMediaName [nvarchar](30) NOT NULL,--媒体位
    DElevator [nvarchar](30) NOT NULL,--电梯
    DUnitName [nvarchar](100) NOT NULL,--门洞
    DFloorUnit [nvarchar](30) NOT NULL,--楼栋 
    DRegionName  [nvarchar](100) NOT NULL  --区域名称
    )
View Code

 

--2、插入by查询(insert select)(和case when then)--条件中尽量不要(字符+、转换类型、isnotnull)操作字段本身

 insert into @details select top (@top) 
   d.[TaskDetailsId]
   ,CASE when acf.AdvertCompanyFloorId is null then @defaultGuid else acf.AdvertCompanyFloorId end
   ,d.[FloorDiscName] 
   ,CASE when acpp.AdvertCompanyPointId is null then @defaultGuid else acpp.AdvertCompanyPointId end 
   ,d.[MediaName]
   ,d.[Elevator]
   ,d.[UnitName]
   ,d.[FloorUnit] 
   ,d.RegionName
   from Task_StageDetails d
   left join Advert_Company_FloorInfo acf on acf.AdvertCompanyFloorName =d.FloorDiscName  
    and acf.AdvertCompanyId=@advertCompanyId
   left join [Advert_Company_PointPositionInfo] acpp on d.FloorUnit = acpp.TungName
        and d.UnitName = acpp.UnitName
        and (d.Elevator = acpp.ElevatorName or d.Elevator = acpp.StoreyName)
        and d.MediaName = acpp.MediaName
        and acf.AdvertCompanyFloorId=acpp.AdvertCompanyFloorId
   where PlanId=@planId and d.AdvertCompanyPointId=@defaultGuid
View Code


--3、更新by子查询(update selec)

--test
select * from test1
--id  number sort s
--1    1    1    2021-01-16 18:02:40.193
--2    2    9    2021-01-16 18:02:40.193
--3    3    3    2021-01-16 18:02:40.193
select * from test2
--id  number sort s
-- 1    1    1    2020-09-19 15:25:07.007
-- 2    2    2    2020-09-19 15:25:07.007

update test1
set sort =
    (select top 1  sort from test2  
    where test1.number=test2.number
    )
where number in (
select t1.number from test1 t1
inner join test2 t2 on t1.number=t2.number
)
go

select * from test1
--id  number sort s
--1    1    1    2021-01-16 18:02:40.193
--2    2    2    2021-01-16 18:02:40.193
--3    3    3    2021-01-16 18:02:40.193
select * from test2
--id  number sort s
-- 1    1    1    2020-09-19 15:25:07.007
-- 2    2    2    2020-09-19 15:25:07.007
View Code

 

--4、linq的select实体内赋值时尽量少使用linq方法,会派生表后再查询一次,数据量大或者有多个linq方法时很慢。
--例如:下面linq中select的//detailsEmp.FirstOrDefault、// detailsEmp.Count,会执行多次查询Task_StageDetails。

--//join联表再Take(1),和在select结果集中赋值查询FirstOrDefault,扫描计数逻辑读取次数是一样的。都是子查询TOP 1,再OUTER APPLY。

items = (from img in db.Set<Task_StagePlanImageName>()
    join plan in db.Set<Task_StagePlanInfo>() on img.PlanId equals plan.PlanId
    join details in db.Set<Task_StageDetails>().Where(where_detail) on new { img.PlanId, img.ImageName } equals new { details.PlanId, ImageName = details.NewAdvertName }
    join collect in db.Set<Task_JobNumberCollectImage>() on new { img.Id } equals new {  Id = collect.ImageId }
    into collectEmp
    from collect in collectEmp.DefaultIfEmpty()
    select new View_Task_JobNumberCollectImage()
    {
        Plan = plan,
        ImageModel = img,
        ImageUrl = "",//detailsEmp.FirstOrDefault().NewAdvertImage,
        ImageTaskCount =0,// detailsEmp.Count(x => x.TaskDetailsId != Guid.Empty),
        JobNumberCollectImageCount = collect.Count,
        MediaSpecs = "",//detailsEmp.FirstOrDefault().MediaSpecs,
        CompanyFloorId = floorIdsIsNull ? Guid.Empty : details.CompanyFloorId,
    }
    ).Where(where_base);
View Code

--不好的linq生成的慢sql。

SELECT 
    [Project8].[Sum] AS [Sum], 
    [Project8].[PlanId1] AS [PlanId], 
    [Project8].[ReleaseState] AS [ReleaseState], 
    [Project8].[PlanNumber] AS [PlanNumber], 
    [Project8].[PlanName] AS [PlanName], 
    [Project8].[InstallTime] AS [InstallTime], 
    [Project8].[ReleaseCount] AS [ReleaseCount], 
    [Project8].[NotTakeCount] AS [NotTakeCount], 
    [Project8].[NotSubmitCount] AS [NotSubmitCount], 
    [Project8].[InstallSuccessCount] AS [InstallSuccessCount], 
    [Project8].[FailEndCount] AS [FailEndCount], 
    [Project8].[NotConfirmCount] AS [NotConfirmCount], 
    [Project8].[CreateTime] AS [CreateTime], 
    [Project8].[CreateUserName] AS [CreateUserName], 
    [Project8].[TrialTime] AS [TrialTime], 
    [Project8].[AdvertCompanyId] AS [AdvertCompanyId], 
    [Project8].[CompanyId] AS [CompanyId], 
    [Project8].[IssueState] AS [IssueState], 
    [Project8].[InstallJobIds] AS [InstallJobIds], 
    [Project8].[StartTime] AS [StartTime], 
    [Project8].[EndTime] AS [EndTime], 
    [Project8].[PlanBatchId] AS [PlanBatchId], 
    [Project8].[Id] AS [Id], 
    [Project8].[PlanId] AS [PlanId1], 
    [Project8].[ImageName] AS [ImageName], 
    [Project8].[CollectCount] AS [CollectCount], 
    [Project8].[Number] AS [Number], 
    [Project8].[C1] AS [C1], 
    [Project8].[C3] AS [C2], 
    [Project8].[Count] AS [Count], 
    [Project8].[C2] AS [C3], 
    CASE WHEN (@p__linq__2 = 1) THEN @p__linq__3 ELSE [Project8].[CompanyFloorId] END AS [C4]
    FROM ( SELECT 
        [Project7].[Id] AS [Id], 
        [Project7].[PlanId] AS [PlanId], 
        [Project7].[ImageName] AS [ImageName], 
        [Project7].[Sum] AS [Sum], 
        [Project7].[CollectCount] AS [CollectCount], 
        [Project7].[Number] AS [Number], 
        [Project7].[PlanId1] AS [PlanId1], 
        [Project7].[ReleaseState] AS [ReleaseState], 
        [Project7].[PlanNumber] AS [PlanNumber], 
        [Project7].[PlanName] AS [PlanName], 
        [Project7].[InstallTime] AS [InstallTime], 
        [Project7].[ReleaseCount] AS [ReleaseCount], 
        [Project7].[NotTakeCount] AS [NotTakeCount], 
        [Project7].[NotSubmitCount] AS [NotSubmitCount], 
        [Project7].[InstallSuccessCount] AS [InstallSuccessCount], 
        [Project7].[FailEndCount] AS [FailEndCount], 
        [Project7].[NotConfirmCount] AS [NotConfirmCount], 
        [Project7].[CreateTime] AS [CreateTime], 
        [Project7].[CreateUserName] AS [CreateUserName], 
        [Project7].[TrialTime] AS [TrialTime], 
        [Project7].[AdvertCompanyId] AS [AdvertCompanyId], 
        [Project7].[CompanyId] AS [CompanyId], 
        [Project7].[IssueState] AS [IssueState], 
        [Project7].[InstallJobIds] AS [InstallJobIds], 
        [Project7].[StartTime] AS [StartTime], 
        [Project7].[EndTime] AS [EndTime], 
        [Project7].[PlanBatchId] AS [PlanBatchId], 
        [Project7].[CompanyFloorId] AS [CompanyFloorId], 
        [Project7].[Count] AS [Count], 
        [Project7].[C1] AS [C1], 
        [Project7].[C2] AS [C2], 
        (SELECT 
            COUNT(1) AS [A1]
            FROM [dbo].[Task_StageDetails] AS [Extent7]
            WHERE ([Extent7].[InstallJobNumberId] = @p__linq__0) AND ([Project7].[PlanId] = [Extent7].[PlanId]) AND ([Project7].[ImageName] = [Extent7].[NewAdvertName]) AND ([Extent7].[TaskDetailsId] <> @p__linq__1)) AS [C3]
        FROM ( SELECT 
            [Project6].[Id] AS [Id], 
            [Project6].[PlanId] AS [PlanId], 
            [Project6].[ImageName] AS [ImageName], 
            [Project6].[Sum] AS [Sum], 
            [Project6].[CollectCount] AS [CollectCount], 
            [Project6].[Number] AS [Number], 
            [Project6].[PlanId1] AS [PlanId1], 
            [Project6].[ReleaseState] AS [ReleaseState], 
            [Project6].[PlanNumber] AS [PlanNumber], 
            [Project6].[PlanName] AS [PlanName], 
            [Project6].[InstallTime] AS [InstallTime], 
            [Project6].[ReleaseCount] AS [ReleaseCount], 
            [Project6].[NotTakeCount] AS [NotTakeCount], 
            [Project6].[NotSubmitCount] AS [NotSubmitCount], 
            [Project6].[InstallSuccessCount] AS [InstallSuccessCount], 
            [Project6].[FailEndCount] AS [FailEndCount], 
            [Project6].[NotConfirmCount] AS [NotConfirmCount], 
            [Project6].[CreateTime] AS [CreateTime], 
            [Project6].[CreateUserName] AS [CreateUserName], 
            [Project6].[TrialTime] AS [TrialTime], 
            [Project6].[AdvertCompanyId] AS [AdvertCompanyId], 
            [Project6].[CompanyId] AS [CompanyId], 
            [Project6].[IssueState] AS [IssueState], 
            [Project6].[InstallJobIds] AS [InstallJobIds], 
            [Project6].[StartTime] AS [StartTime], 
            [Project6].[EndTime] AS [EndTime], 
            [Project6].[PlanBatchId] AS [PlanBatchId], 
            [Project6].[CompanyFloorId] AS [CompanyFloorId], 
            [Project6].[Count] AS [Count], 
            [Project6].[C1] AS [C1], 
            [Project6].[C2] AS [C2]
            FROM ( SELECT 
                [Project4].[Id] AS [Id], 
                [Project4].[PlanId] AS [PlanId], 
                [Project4].[ImageName] AS [ImageName], 
                [Project4].[Sum] AS [Sum], 
                [Project4].[CollectCount] AS [CollectCount], 
                [Project4].[Number] AS [Number], 
                [Project4].[PlanId1] AS [PlanId1], 
                [Project4].[ReleaseState] AS [ReleaseState], 
                [Project4].[PlanNumber] AS [PlanNumber], 
                [Project4].[PlanName] AS [PlanName], 
                [Project4].[InstallTime] AS [InstallTime], 
                [Project4].[ReleaseCount] AS [ReleaseCount], 
                [Project4].[NotTakeCount] AS [NotTakeCount], 
                [Project4].[NotSubmitCount] AS [NotSubmitCount], 
                [Project4].[InstallSuccessCount] AS [InstallSuccessCount], 
                [Project4].[FailEndCount] AS [FailEndCount], 
                [Project4].[NotConfirmCount] AS [NotConfirmCount], 
                [Project4].[CreateTime] AS [CreateTime], 
                [Project4].[CreateUserName] AS [CreateUserName], 
                [Project4].[TrialTime] AS [TrialTime], 
                [Project4].[AdvertCompanyId] AS [AdvertCompanyId], 
                [Project4].[CompanyId] AS [CompanyId], 
                [Project4].[IssueState] AS [IssueState], 
                [Project4].[InstallJobIds] AS [InstallJobIds], 
                [Project4].[StartTime] AS [StartTime], 
                [Project4].[EndTime] AS [EndTime], 
                [Project4].[PlanBatchId] AS [PlanBatchId], 
                [Project4].[CompanyFloorId] AS [CompanyFloorId], 
                [Project4].[Count] AS [Count], 
                [Project4].[C1] AS [C1], 
                (SELECT TOP (1) 
                    [Extent6].[MediaSpecs] AS [MediaSpecs]
                    FROM [dbo].[Task_StageDetails] AS [Extent6]
                    WHERE ([Extent6].[InstallJobNumberId] = @p__linq__0) AND ([Project4].[PlanId] = [Extent6].[PlanId]) AND ([Project4].[ImageName] = [Extent6].[NewAdvertName])) AS [C2]
                FROM ( SELECT 
                    [Project3].[Id] AS [Id], 
                    [Project3].[PlanId] AS [PlanId], 
                    [Project3].[ImageName] AS [ImageName], 
                    [Project3].[Sum] AS [Sum], 
                    [Project3].[CollectCount] AS [CollectCount], 
                    [Project3].[Number] AS [Number], 
                    [Project3].[PlanId1] AS [PlanId1], 
                    [Project3].[ReleaseState] AS [ReleaseState], 
                    [Project3].[PlanNumber] AS [PlanNumber], 
                    [Project3].[PlanName] AS [PlanName], 
                    [Project3].[InstallTime] AS [InstallTime], 
                    [Project3].[ReleaseCount] AS [ReleaseCount], 
                    [Project3].[NotTakeCount] AS [NotTakeCount], 
                    [Project3].[NotSubmitCount] AS [NotSubmitCount], 
                    [Project3].[InstallSuccessCount] AS [InstallSuccessCount], 
                    [Project3].[FailEndCount] AS [FailEndCount], 
                    [Project3].[NotConfirmCount] AS [NotConfirmCount], 
                    [Project3].[CreateTime] AS [CreateTime], 
                    [Project3].[CreateUserName] AS [CreateUserName], 
                    [Project3].[TrialTime] AS [TrialTime], 
                    [Project3].[AdvertCompanyId] AS [AdvertCompanyId], 
                    [Project3].[CompanyId] AS [CompanyId], 
                    [Project3].[IssueState] AS [IssueState], 
                    [Project3].[InstallJobIds] AS [InstallJobIds], 
                    [Project3].[StartTime] AS [StartTime], 
                    [Project3].[EndTime] AS [EndTime], 
                    [Project3].[PlanBatchId] AS [PlanBatchId], 
                    [Project3].[CompanyFloorId] AS [CompanyFloorId], 
                    [Project3].[Count] AS [Count], 
                    [Project3].[C1] AS [C1]
                    FROM ( SELECT 
                        [Project1].[Id] AS [Id], 
                        [Project1].[PlanId] AS [PlanId], 
                        [Project1].[ImageName] AS [ImageName], 
                        [Project1].[Sum] AS [Sum], 
                        [Project1].[CollectCount] AS [CollectCount], 
                        [Project1].[Number] AS [Number], 
                        [Project1].[PlanId1] AS [PlanId1], 
                        [Project1].[ReleaseState] AS [ReleaseState], 
                        [Project1].[PlanNumber] AS [PlanNumber], 
                        [Project1].[PlanName] AS [PlanName], 
                        [Project1].[InstallTime] AS [InstallTime], 
                        [Project1].[ReleaseCount] AS [ReleaseCount], 
                        [Project1].[NotTakeCount] AS [NotTakeCount], 
                        [Project1].[NotSubmitCount] AS [NotSubmitCount], 
                        [Project1].[InstallSuccessCount] AS [InstallSuccessCount], 
                        [Project1].[FailEndCount] AS [FailEndCount], 
                        [Project1].[NotConfirmCount] AS [NotConfirmCount], 
                        [Project1].[CreateTime] AS [CreateTime], 
                        [Project1].[CreateUserName] AS [CreateUserName], 
                        [Project1].[TrialTime] AS [TrialTime], 
                        [Project1].[AdvertCompanyId] AS [AdvertCompanyId], 
                        [Project1].[CompanyId] AS [CompanyId], 
                        [Project1].[IssueState] AS [IssueState], 
                        [Project1].[InstallJobIds] AS [InstallJobIds], 
                        [Project1].[StartTime] AS [StartTime], 
                        [Project1].[EndTime] AS [EndTime], 
                        [Project1].[PlanBatchId] AS [PlanBatchId], 
                        [Project1].[CompanyFloorId] AS [CompanyFloorId], 
                        [Project1].[Count] AS [Count], 
                        (SELECT TOP (1) 
                            [Extent5].[NewAdvertImage] AS [NewAdvertImage]
                            FROM [dbo].[Task_StageDetails] AS [Extent5]
                            WHERE ([Extent5].[InstallJobNumberId] = @p__linq__0) AND ([Project1].[PlanId] = [Extent5].[PlanId]) AND ([Project1].[ImageName] = [Extent5].[NewAdvertName])) AS [C1]
                        FROM ( SELECT 
                            [Extent1].[Id] AS [Id], 
                            [Extent1].[PlanId] AS [PlanId], 
                            [Extent1].[ImageName] AS [ImageName], 
                            [Extent1].[Sum] AS [Sum], 
                            [Extent1].[CollectCount] AS [CollectCount], 
                            [Extent1].[Number] AS [Number], 
                            [Extent2].[PlanId] AS [PlanId1], 
                            [Extent2].[ReleaseState] AS [ReleaseState], 
                            [Extent2].[PlanNumber] AS [PlanNumber], 
                            [Extent2].[PlanName] AS [PlanName], 
                            [Extent2].[InstallTime] AS [InstallTime], 
                            [Extent2].[ReleaseCount] AS [ReleaseCount], 
                            [Extent2].[NotTakeCount] AS [NotTakeCount], 
                            [Extent2].[NotSubmitCount] AS [NotSubmitCount], 
                            [Extent2].[InstallSuccessCount] AS [InstallSuccessCount], 
                            [Extent2].[FailEndCount] AS [FailEndCount], 
                            [Extent2].[NotConfirmCount] AS [NotConfirmCount], 
                            [Extent2].[CreateTime] AS [CreateTime], 
                            [Extent2].[CreateUserName] AS [CreateUserName], 
                            [Extent2].[TrialTime] AS [TrialTime], 
                            [Extent2].[AdvertCompanyId] AS [AdvertCompanyId], 
                            [Extent2].[CompanyId] AS [CompanyId], 
                            [Extent2].[IssueState] AS [IssueState], 
                            [Extent2].[InstallJobIds] AS [InstallJobIds], 
                            [Extent2].[StartTime] AS [StartTime], 
                            [Extent2].[EndTime] AS [EndTime], 
                            [Extent2].[PlanBatchId] AS [PlanBatchId], 
                            [Extent3].[CompanyFloorId] AS [CompanyFloorId], 
                            [Extent4].[Count] AS [Count]
                            FROM    [dbo].[Task_StagePlanImageName] AS [Extent1]
                            INNER JOIN [dbo].[Task_StagePlanInfo] AS [Extent2] ON [Extent1].[PlanId] = [Extent2].[PlanId]
                            LEFT OUTER JOIN [dbo].[Task_StageDetails] AS [Extent3] ON ([Extent3].[InstallJobNumberId] = @p__linq__0) AND ([Extent1].[PlanId] = [Extent3].[PlanId]) AND ([Extent1].[ImageName] = [Extent3].[NewAdvertName])
                            LEFT OUTER JOIN [dbo].[Task_JobNumberCollectImage] AS [Extent4] ON [Extent1].[Id] = [Extent4].[ImageId]
                        )  AS [Project1]
                    )  AS [Project3]
                )  AS [Project4]
            )  AS [Project6]
        )  AS [Project7]
    )  AS [Project8]
    WHERE [Project8].[C3] > 0
View Cod

 

--5、sqlserver执行大量数据update select时,用中间表代替select的大量数据,避免执行慢(推测原因是阻塞和锁,以及每一次子查询的where执行消耗)。

--任务视图中间表更新
    truncate table  Table_TaskNoAdvertPoint
    insert into Table_TaskNoAdvertPoint
        select   
        distinct
        d.[TaskDetailsId] as DTaskDetailsId
        ,d.PlanId as DPlanId
        ,CASE when acf.AdvertCompanyFloorId is null then '00000000-0000-0000-0000-000000000000' else acf.AdvertCompanyFloorId end as DAdvertCompanyFloorId
        --,acf.AdvertCompanyFloorId as DAdvertCompanyFloorId
        ,d.[FloorDiscName]  as DFloorDiscName
        ,CASE when acpp.AdvertCompanyPointId is null then '00000000-0000-0000-0000-000000000000' else acpp.AdvertCompanyPointId end  as DAdvertCompanyPointId
        --,acpp.AdvertCompanyPointId as DAdvertCompanyPointId
        ,d.[MediaName] as DMediaName
        ,d.[Elevator] as DElevator
        ,d.[UnitName] as DUnitName
        ,d.[FloorUnit]  as DFloorUnit
        ,d.RegionName as DRegionName
        from Task_StageDetails d
        left join Advert_Company_FloorInfo acf on acf.AdvertCompanyFloorName =d.FloorDiscName  
        and acf.AdvertCompanyId=d.AdvertCompanyId
        left join [Advert_Company_PointPositionInfo] acpp on d.FloorUnit = acpp.TungName
            and d.UnitName = acpp.UnitName
            and (d.Elevator = acpp.ElevatorName or d.Elevator = acpp.StoreyName)
            and d.MediaName = acpp.MediaName
            and acf.AdvertCompanyFloorId=acpp.AdvertCompanyFloorId
        where d.AdvertCompanyPointId= '00000000-0000-0000-0000-000000000000'
        and  d.planid=@planId
           
    --匹配楼盘
    update Task_StageDetails  set AdvertCompanyFloorId
    = (select top 1 DAdvertCompanyFloorId from Table_TaskNoAdvertPoint d
        where Task_StageDetails.TaskDetailsId=d.DTaskDetailsId
        )
    where  Task_StageDetails.TaskDetailsId
    in (select   DTaskDetailsId from Table_TaskNoAdvertPoint where DPlanId=@planId
    )

    --匹配点位
    update Task_StageDetails  set AdvertCompanyPointId  
    = (select top 1 DAdvertCompanyPointId  from Table_TaskNoAdvertPoint d
        where Task_StageDetails.TaskDetailsId=d.DTaskDetailsId
        )
    where  Task_StageDetails.TaskDetailsId
    in (select   DTaskDetailsId from Table_TaskNoAdvertPoint  where DPlanId=@planId
    )
    
View Code

 

--6、查看sql执行的计划

DBCC DROPCLEANBUFFERS  --清空缓存

-- set statistics profile on

-- SET STATISTICS TIME ON

SET STATISTICS IO ON  --开启IO统计

逻辑读取LOB逻辑读取,是在性能调优时的重点。通常创建合适的索引或重写查询可以彻底降低。

https://www.cnblogs.com/woodytu/p/4535658.html

扫描计数(Scan count):

根据微软在线帮助,扫描计数是在任何方向都达到叶级别后启动的查询/扫描数,目的在于检索用于构造输出的最终数据集的所有值。

    如果使用的索引是主键的唯一索引或聚集索引并且您仅查找一个值,则扫描计数为 0。 例如 WHERE Primary_Key_Column = <value>。

    当您使用对非主键列定义的非唯一的聚集索引搜索一个值时,扫描计数为 1。 这是为了针对您正在搜索的键值检查重复值。 例如 WHERE Clustered_Index_Key_Column = <value>。

    当 N 为通过使用索引键定位键值后,在叶级别的左侧或右侧启动的不同查找/扫描数时,则扫描计数为 N。

这个数字告诉我们优化器所选择的计划,对这个对象的重复读取次数。很多人误以为这个是对整张表的读取次数,这是完全错误的。

我们通过一个例子来理解扫描计数。
复制代码

 1 CREATE TABLE ScanCount (Id INT IDENTITY(1,1),Value CHAR(1))
 2 INSERT INTO ScanCount (Value ) VALUES ('A') ,('B'),('C'),('D'), ('E') , ('F') 
 3 CREATE UNIQUE CLUSTERED INDEX ix_ScanCount ON ScanCount(Id)
 4 
 5 SET STATISTICS IO ON
 6 --Unique clustered Index used to search single value
 7 SELECT * FROM ScanCount  WHERE Id =1
 8 --Unique clustered Index used to search multiple value
 9 SELECT * FROM ScanCount  WHERE Id IN(1,2,3,4,5,6)
10 --Unique clustered Index used to search multiple value
11 SELECT * FROM ScanCount  WHERE Id BETWEEN 1 AND 6

复制代码

我们来看下上面3个查询语句的输出。

在第1个SELECT语句的输出里,扫描计数为0。这和MSDN里在线帮助“如果使用的索引是主键的唯一索引或聚集索引并且您仅查找一个值,则扫描计数为 0。”描述一致。因为它是唯一索引(聚集/非聚集索引),不需要在叶子层,进行进一步的向左或向右扫描,因为这里只有一个值来匹配。那也是在唯一索引上查找单一值,扫描计数为0的原因。扫描计数是1的话,会在非唯一索引(聚集或非聚集索引)上发生。

对于第2个SELECT语句,扫描计数是6.这是因为我们在找多个不同值。MSDN在线帮助对此有详细说明: “如果使用的索引是主键的唯一索引或非聚集索引,你在查找N个值,则扫描计数为N。”。

我们来看看执行计划里的SEEK谓语,将更清晰:

即使只有一个where条件,还是会分裂成多个谓语。对于每个SEEK谓语,它会生成1个扫描数。

对于最后一个SELECT语句,扫描计数为1,因为MSDN在线帮助说了: “当 N 为通过使用索引键定位键值后,在叶级别的左侧或右侧启动的不同查找/扫描数时,则扫描计数为 N。” 在叶子节点聚集索引结构用来找到1值后,叶子层的向左扫描开始,直到找到值6。我们看下执行计划里的SEEK 谓语,将更清晰:

逻辑读取(logical Read):

从数据缓存读取的页数。数字越小,性能越好。在性能调优中这个数字非常重要。因为它不会随着执行又执行而改变,除非数据或查询语句有变动。在进行性能调优时,这个可以作为性能提升的重要参考。
物理读取(physical reads):

从磁盘读取的页数。这个会随着执行又执行而改变。大多数情况下,连续第2次的执行时,它的物理读取值为0(可以参考上面连续查询的物理读取数变化)。

如果连续执行后,物理读取次数下降了,我们可以假定是服务器上内存使用配置的错误,或者服务器工作量饱和,有内存压力。你需要在服务器级别思考问题的原因。在查询调优时,这个数字不太重要,因为它一直在变,对于下降这个值,你不能对它做出太多控制。
预读 (read-ahead reads):

为进行查询而放入缓存的页数。这个值告诉我们物理页读取数,即SQL Server执行的,作为预读机制的一部分。在查询执行请求那些可能用到页之前,SQL Server把物理数据页读入缓存,用于完成接下来查询的页需要。

可以看到,物理读取是2次,预读是946次。这就是说,查询执行请求了2个页,并预读了946个页到数据缓存,SQL Server估计下次查询可能要用到这些页。和物理读取一样,这个值对在查询调优里并不重要。
lob 逻辑读取(lob logical reads):

从数据缓存读取的 text、ntext、image 或大值类型 (varchar(max)、nvarchar(max)、varbinary(max)) 页的数目。这个和逻辑读一样重要,我们要非常重视。
lob 物理读取(lob physical reads):

从磁盘读取的 text、ntext、image 或大值类型页的数目。
lob 预读(lob read-ahead reads):

为进行查询而放入缓存的 text、ntext、image 或大值类型页的数目。

总结下,逻辑读取和LOB逻辑读取是2个重要数值,在性能调优时,我们要重点围观。如果把这2个值调低,不在本文的讨论范围。通常创建合适的索引或重写查询可以帮助我们彻底降低这2个值。
View Code

 

 

--7、查询是否区分大小写

设置某表某列:  alter table TableName ALTER Column ColumnName nvarchar(200) COLLATE Chinese_PRC_CS_AS   --(Chinese_PRC_CS_AS  区分,Chinese_PRC_CI_AS 不区分)

当次查询:

select * from TableName where ColumnName collate Chinese_PRC_CS_AS=‘value‘ --区分

select * from TableName where ColumnName collate Chinese_PRC_CS_AS like ‘value%‘ --不区分

或者转二进制查询。

 

--8、left join和where in相遇
//where存在in时,select列或group列包含left join的表字段,会慢。使用inner或where的in前面增加使用到leftjoin的表的字段增加条件 is not null。

例如
//--视图内有leftjoin,使用in条件需要再in前加left的非空条件
List<View_OrderGetNucleateView> nucleates = DBSession.IView_OrderGetNucleateViewDAL.GetListViewBy(x =>x.SampleNumber!=null && batchNumbers.Contains(x.BatchNumberNucleicAcid));

例如
SELECT dbo.Order_GetNucleate.BatchNumberNucleicAcid
,dbo.Order_GetNucleate.StateNucleicAcid
,dbo.Member_PetSampleBox.SampleNumber
,count(dbo.Member_PetSampleBox.SampleNumber) as [Count]
FROM dbo.Order_GetNucleate
left JOIN dbo.Member_PetSampleBox ON dbo.Member_PetSampleBox.PetIds = dbo.Order_GetNucleate.PetIds
AND dbo.Member_PetSampleBox.IsEffective = 1
AND dbo.Member_PetSampleBox.SampleType = dbo.Order_GetNucleate.SampleType
AND dbo.Member_PetSampleBox.BoxType != 1
--这里需要加is not null,或改成inner join
where dbo.Member_PetSampleBox.SampleNumber is not null and BatchNumberNucleicAcid in ('20230626-3C','20230626-2C','20230626-1Y','20230621-1Y','20230620-2C','20230620-1Y','20230619-1Y','20230618-2C','20230618-1Y','20230616-2C','20230616-1Y','20230615-1Y','20230614-2C','20230614-1Y','20230613-1Y','20230612-3C','20230612-2Y','20230612-1Y','20230609-1Y','20230608-1Y')

group by dbo.Order_GetNucleate.BatchNumberNucleicAcid
,dbo.Order_GetNucleate.StateNucleicAcid
,dbo.Member_PetSampleBox.SampleNumber

 

--9、修改表名列名

--例:
use SmartLockAccountAndOrderDB
go

--修改表名
exec sp_rename 'Lock_OpenConfig','Lock_OpenConfigOrder'
go

--修改表Lock_OpenConfigOrder的列名updated,改为Updated。
exec sp_rename 'Lock_OpenConfigOrder.updated','Updated','COLUMN'




--10、记录事务和锁
--事务隔离级别,读未提交 READ UNCOMMITTED,读已提交 Read Committed,可重复读 Repeatable Read,序列化 Serializable。
--隔离级别当前事务去操作其他事务锁住资源的规则,和其他事务操作当前事务锁住资源的规则。
--读未提交:READ UNCOMMITTED
--会读取其他事务未提交的可变数据,不阻塞当前事务查询。
--读操作不申请共享锁,不阻塞其他事务更新。

--读已提交:Read Committed
--不会读取到其他事务未提交的可变数据,不阻塞当前事务查询。
--读完释放共享锁,不阻塞由其他事务更新。

--可重复读:Repeatable Read
--在一个事务中对相同KEY多次读取是重复的,阻塞首次查询可变数据。
--如果先查询过KEY,其他事物再操作,二次查询相同的KEY不阻塞。当前事务没查过的,其他事务更新或新增的未提交KEY,则是首次查询会阻塞。
--读取申请共享锁保持到当前事务完成,阻塞其他事务更新当前事务查询过的数据。
--读取不申请域锁,不阻塞其他事务新增。

--序列化:Serializable
--每次都从数据库读取,阻塞首次查询可变数据。
--如果先查询过KEY,其他事物再操作,二次查询相同的KEY不阻塞,不会查询到其他事务新增的未提交KEY。
--读取申请共享锁保持到当前事务完成,阻塞其他事务更新当前事务查询过的数据。
--读取申请域锁,阻塞其他事务新增当前事务查询过的域(where条件的域,比如当前事务进行用户手机号验重,第二个事物添加相同手机号阻塞)。
--新增和更新申请域锁X,阻塞第二个序列化事务查询当前事务set修改的字段。

--共享锁造成的阻塞才可以降低事务隔离级别。因为排他锁都是修改或新增申请,直到事务结束才释放。
--////使用事务TransactionScope-Serializable或可重复读级别,//如果在事务内查询表A,再修改或新增表A,并发会死锁。两个线程申请共享锁S,又同时申请排他锁X。
--////单程序系统可以使用快照隔离级别加代码锁lock,实现数据验重和查旧数据计算新值。是把事务阻塞转移到了代码锁,但代码锁只适合单程序系统。
--////查询旧值最好用主键减少行锁,计如果算新值允许负值,可以在更新语句中计算,减少事务内查询。
--////验重有条件的还是用唯一索引限制,事务内查询验重还是容易有阻塞。
--要在事务中实现数据验重和查旧数据计算新值,可以在事务中先查询需要锁住的数据,并手动使用锁。注意给验重查询where的字段增加索引或用主键查询,减少行锁。
--手动加更新锁U阻止并发事务更新。对于查询旧值重新计算的情况,应该加排他锁X,其他事务不能查询了尽量用主键查询避免阻塞。
set transaction isolation level Serializable -- Repeatable Read
begin tran
    --手动加更新锁U并保持不释放,不阻塞其他线程默认查询申请S锁。并发线程会阻塞更新。
    --查询字段是主键时TAB:IX,PAG:IU,KEY:U。    
    --select * from Temp_Json WITH (UPDLOCK, HOLDLOCK) where  IntId=20
    --查询条件字段没有索引时TAB:X。即使加了索引没查到数据也容易有阻塞,最好还是用唯一索引限制重复。
    --select * from Temp_PakResult WITH (UPDLOCK, HOLDLOCK) where PakResult='333'
    --查询字段有索引,没查询到数据PAG:IU,PAG:IU,TAB:IX,KEY:RangeS-U
    --select * from Order_Main WITH (UPDLOCK, HOLDLOCK) where OrderNo='333'
    --查询字段有索引,有查询到数据PAG:IU,PAG:IU,TAB:IX,KEY:U,KEY:U
    --select * from Order_Main WITH (UPDLOCK, HOLDLOCK) where OrderNo='2019072505440286d6'
    --手动加排他锁,KEY:X,TAB:IX,PAG:IX
    --select * from Temp_Json WITH (XLOCK, HOLDLOCK) where  IntId=20

    --waitfor delay '00:00:5'--等待秒

    --Update Temp_Json set [Json]='222' where  IntId=20
    -- INSERT INTO [dbo].[Temp_PakResult] ([Id] ,[PakResult]) VALUES (newid(),CONVERT(varchar(100), GETDATE(), 121))
    --INSERT INTO [dbo].[Temp_PakResult] ([Id] ,[PakResult]) VALUES (newid(),'333')

    waitfor delay '00:00:5'--等待秒
--rollback tran
commit tran   

--查看所有锁
EXEC sp_lock;
--查看表的锁
SELECT
    request_session_id AS 'Session ID',
    resource_type AS 'Resource Type',
    resource_associated_entity_id AS 'Resource ID',
    resource_database_id AS 'Database ID',
    request_mode AS 'Lock Requested',
    request_status AS 'Lock Status'
FROM
    sys.dm_tran_locks
WHERE
    resource_database_id = DB_ID() AND
    resource_associated_entity_id = OBJECT_ID('Temp_Json') -- OBJECT_ID 表名


 

posted @ 2021-01-25 15:14  lanofsky  阅读(227)  评论(0)    收藏  举报