简介: 在我们的应用程序中,我们利用 Dapper ORM 与 SQL Server 数据库进行交互。我们的关键表之一,OperationSteps,随着时间的推移显着增长,导致性能问题,特别是在查询执行期间。这篇文章旨在探索在使用 Dapper ORM 时优化 SQL Server 中大型表的查询性能的策略。
表定义: 让我们首先检查 GameSessions 表的结构:
CREATE TABLE [dbo].[OperationSteps](
[UserId] [int] NOT NULL,
[OperationName] [nvarchar](300) NOT NULL,
[FatherName] [nvarchar](50) NOT NULL,
[EventType] [nvarchar](5) NOT NULL,
[StepId] [nvarchar](100) NOT NULL,
[TransactionId] [nvarchar](200) NOT NULL,
[Amount] [float] NOT NULL,
[TimeStamp] [datetime] NOT NULL,
[OperationIdExternal] [nvarchar](max) NULL,
[TaxesAmount] [decimal](19, 4) NULL,
[Round] [nvarchar](max) NULL,
[FatherId] [smallint] NULL,
CONSTRAINT [PK_OperationSteps] PRIMARY KEY NONCLUSTERED
(
[UserId] ASC,
[TransactionId] ASC,
[StepsId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
所有选择 stmt 中包含的字段
SELECT
UserId,
OperationName,
OperationIdExternal AS GameId,
ProviderId,
ProviderName,
EventType,
StepId,
TransactionId,
Amount,
TimeStamp,
TaxesAmount,
Round
查询Where子句
在我们的查询中,我们使用以下 where 子句:
1)
WHERE [ProviderId] = @ProviderId
AND [OperationIdExternal] = @GameId
AND [Round] = @Round
AND [EventType] = @EventType
WHERE [ProviderId] = @ProviderId
AND (@TransactionId IS NULL OR [TransactionId] = @TransactionId)
AND (@Round IS NULL OR [Round] = @Round)
AND (@EventType IS NULL OR [EventType] = @EventType)
AND (@OperationId IS NULL OR [OperationIdExternal] = @OperationId)
在代码方面我有(只有一块):
FROM dbo.OperationsSteps
WHERE ProviderId = @ProviderId";
var parameters = new DynamicParameters();
parameters.Add("@ProviderId", providerId, DbType.Int16, ParameterDirection.Input);
if (!string.IsNullOrEmpty(transactionId))
{
query += " AND TransactionId = @TransactionId";
parameters.Add("@TransactionId", transactionId, DbType.String, ParameterDirection.Input);
}
if (!string.IsNullOrEmpty(round))
{
query += " AND Round = @Round";
parameters.Add("@Round", round, DbType.String, ParameterDirection.Input);
}
WHERE [SessionId] = @SessionId
AND [Round] = @Round
AND [EventType] = @EventType
记录数 该表有大量记录,范围从 5,000,000 到 15,000,000。
我尝试对表的结构进行以下更改:
ALTER TABLE dbo.OperationSteps
ALTER COLUMN Round nvarchar(100);
CREATE NONCLUSTERED INDEX IX_OperationSteps_Operation_Round_EventType
ON dbo.OperationSessions (StepId, Round, EventType);
但是查询超时并锁定表。
总结: 我在 SQL Server 数据库中包含数百万条记录的大型表上执行查询时遇到性能问题。尽管使用 Dapper 进行数据库交互,但由于索引扫描,查询仍需要 2-3 秒的时间来执行。我正在寻求有关在不影响应用程序可用性的情况下提高查询性能的建议。
如果您提供有关在应用程序保持在线状态时优化查询性能的任何建议或见解,我将不胜感激。
我看到这个索引:
CREATE NONCLUSTERED INDEX IX_OperationSteps_Operation_Round_EventType
ON dbo.OperationSessions (StepId, Round, EventType);
但它根本不匹配任何
WHERE
子句选项。尝试将 ProviderID
设置为该索引中的第一列,而不是 StepID
。您可以选择添加一个 INCLUDE
指令以及查询中其他列的索引,这将允许数据库完全仅从索引提供查询服务。但是,根据您的工作负载,这可能增加的成本超过您获得的收益,因此您需要仔细测试它。
那么您可能还想为
(SessionID, Round, EventType)
添加另一个非聚集索引