Sql 查询和表优化
` 上面查询中提到的一个名为Sql 查询和表优化,sql,sql-server,Sql,Sql Server,` 上面查询中提到的一个名为ParentFormResponses的表有3条以上的LACS记录。表并没有任何标识列,而是我基于唯一性在一些列的组上创建了聚集主索引。但执行一个简单的select语句仍然需要16分钟以上,即从ParentFormResponses执行select* 若我要从上述select语句中删除ParentFormResponses表的列名,那个么它将在2-3秒内显示结果,但对于上述查询,它花费了太多时间 如果我在entityid和entitytypeid上创建非聚集索引,那么
ParentFormResponses
的表有3条以上的LACS记录。表并没有任何标识列,而是我基于唯一性在一些列的组上创建了聚集主索引。但执行一个简单的select语句仍然需要16分钟以上,即从ParentFormResponses执行select*
若我要从上述select语句中删除ParentFormResponses表的列名,那个么它将在2-3秒内显示结果,但对于上述查询,它花费了太多时间
如果我在entityid
和entitytypeid上创建非聚集索引,那么它也不会给出优化结果
请建议我如何改进表结构和查询性能
详细信息:
表结构:
SELECT DISTINCT ECS.UserId,,PFR.EntityId,PFR.CreatedBy
FROM EventConsentStatus ECS
INNER JOIN @Institutions I ON ECS.InstitutionId=I.InstitutionId
LEFT JOIN ParentFormResponses PFR ON PFR.EntityTypeId = 1
AND PFR.EntityId=@ActivityId AND ECS.EventId=PFR.EntityId
WHERE ECS.EventId = @ActivityId
约束[PK_ParentFormResponses]主键群集
(
[EntityId]ASC,
[FormId]ASC,
[学生ID]ASC,
[EntityTypeId]ASC,
[格式版本]ASC
)(PAD_INDEX=OFF,STATISTICS_norecomputer=OFF,IGNORE_DUP_KEY=OFF,ALLOW_ROW_LOCKS=ON,ALLOW_PAGE_LOCKS=ON,FILLFACTOR=90)打开[主]
)在[小学]`
=>我删除了主键索引,并在非聚集索引下面创建了索引
在[dbo].[ParentFormResponses\u sakshi]上创建非聚集索引[IX\u ParentFormResponses\u sakshi\u EntityId]
(
[EntityId]ASC,
[EntityTypeId]ASC,
[FormId]ASC,
[格式版本]ASC
)
包括([StudentId],
[CreatedBy]),在[PRIMARY]上启用(PAD_INDEX=OFF、STATISTICS_norecocomputer=OFF、SORT_IN_TEMPDB=OFF、DROP_EXISTING=OFF、ONLINE=OFF、ALLOW_ROW_LOCKS=ON、ALLOW_PAGE_LOCKS=ON)
去
=>基于使用的sp_空间的所有三个表的结果为-
注:记录数量不是30k,而是超过3个LAC。我写错了。从性能角度来看,
distinct
和left join
的组合是可疑的。首先,检查以下查询:
`CREATE TABLE [dbo].[ParentFormResponses](
[EntityId] [int] NOT NULL,
[FormId] [int] NOT NULL,
[StudentId] [nvarchar](50) NOT NULL,
[CreatedBy] [nvarchar](50) NOT NULL,
[CreatedOn] [datetime] NOT NULL,
[EntityTypeId] [int] NOT NULL,
[FormVersion] [decimal](18, 1) NOT NULL,
[DigitallySigned] [bit] NULL,
[HasResponseChanged] [bit] NULL,
您可以使用eventapproverstatus(EventId,UserId)
上的索引对此进行优化。假设这具有良好的性能,它将生成正确的行集。如果没有,则您可能会从@institutions
获得副本。如果是这种情况,那么考虑移除它(从该表中不使用列,它仅用于过滤)。或:
为了获得正确的值,让我们使用outer apply
获取附加数据:
SELECT ECS.UserId, ECS.EntityId
FROM EventConsentStatus ECS
WHERE ECS.EventId = @ActivityId AND
EXISTS (SELECT 1 FROM @Institutions I WHERE ECS.InstitutionId = I.InstitutionId)
为此,您需要在
ParentFormResponses(EntityId、EntityTypeID、CreatedBy)上建立索引您知道什么是查询计划吗?如果没有-读取已启动。然后把它寄出去。这就是说,从创造明显的盈余开始。这可能需要在tempdb上做很多工作,但是查询计划会告诉您。从这样一个小的表中选择数据不会花费太长时间。一定是抓取过程花了这么长时间。您是否在存储大数据(图像、视频等)?我假设从ParentFormResponses中选择count(*)只需几秒钟。对的至于连接:您提到的EntityId和EntityTypeId索引通常应该使其快速,至少当存在许多不同的EntityId时。另一个问题:估计有多少用户在运行查询时访问表ParentFormResponses?发布查询计划。。另外,请确保您创建的非聚集索引正在实际使用,并且统计信息是最新的。尝试使用group by而不是DISTINCE尝试使用适当的索引进行外部应用,但仍然花费了太多时间。如果我同时运行两个查询,一个在外部apply中,另一个单独运行,那么只需几秒钟。但使用左连接或外部应用不会给出优化结果。@Sakshi。我刚刚更新了索引定义。我误读了一个相关的join
条件——这会影响索引和性能。
SELECT ECS.UserId, ECS.EntityId
FROM EventConsentStatus ECS
WHERE ECS.EventId = @ActivityId AND
EXISTS (SELECT 1 FROM @Institutions I WHERE ECS.InstitutionId = I.InstitutionId)
SELECT ECS.UserId, PFR.EntityId, PFR.CreatedBy
FROM EventConsentStatus ECS INNER JOIN
@Institutions I
ON ECS.InstitutionId = I.InstitutionId OUTER APPLY
(SELECT TOP 1 PFR.EntityId, PFR.CreatedBy
FROM ParentFormResponses pfr
WHERE ECS.EventId = PFR.EntityId AND
PFR.EntityTypeId = 1 AND
PFR.EntityId = @ActivityId
) pfr
WHERE ECS.EventId = @ActivityId;