【问题标题】:Slow Performance when ORDER BY in SQL Server在 SQL Server 中进行 ORDER BY 时性能下降
【发布时间】:2015-05-12 09:14:52
【问题描述】:

我正在开发一个项目(Microsoft SQL Server 2012),我确实需要在其中存储一些数据。 目前我的表总共包含 1441352 条记录。

表结构如下:

  • RecordIdentifier(整数,非空)
  • GlnCode(PK,nvarchar(100),不为空)
  • 说明(nvarchar(MAX),不为空)
  • VendorId (nvarchar(100), not null)
  • 供应商名称(nvarchar(100),不为空)
  • ItemNumber(PK,nvarchar(100),不为空)
  • ItemUOM(PK,nvarchar(128),不为空)

我的表格在以下字段中被索引:

  • NonClustered - GlnCode,升序
  • NonClustered - ItemNumber,升序
  • NonClustered - ItemUOM,升序
  • NonClustered - VendorID,升序
  • 集群 - 唯一(以上 4 列加在一起)。

现在,当我编写一个 API 来返回表中的记录时。 API 公开方法并执行此查询:

SELECT TOP (51) 
    [GlnCode] AS [GlnCode], 
    [VendorId] AS [VendorId], 
    [ItemNumber] AS [ItemNumber], 
    [ItemUOM] AS [ItemUOM], 
    [RecordIdentitifer] AS [RecordIdentitifer], 
    [Description] AS [Description], 
    [VendorName] AS [VendorName]
FROM [dbo].[T_GENERIC_ARTICLE]

如果我看性能,这很好。 但是,这并不能保证我总是返回相同的集合,所以我需要应用 ORDER BY 子句,这意味着正在执行的查询如下所示:

SELECT TOP (51) 
    [GlnCode] AS [GlnCode], 
    [VendorId] AS [VendorId], 
    [ItemNumber] AS [ItemNumber], 
    [ItemUOM] AS [ItemUOM], 
    [RecordIdentitifer] AS [RecordIdentitifer], 
    [Description] AS [Description], 
    [VendorName] AS [VendorName]
    FROM [dbo].[T_GENERIC_ARTICLE]
    ORDER BY [GlnCode] ASC, [ItemNumber] ASC, [ItemUOM] ASC, [VendorId] ASC

现在,查询需要几秒钟才能返回,这是我无法承受的。

有人知道如何解决这个问题吗?

【问题讨论】:

  • 我是一个 mySQL 人,但我想在 100 char varchar 字段上对大结果进行排序会很慢。您可能想尝试添加一个更小的 varchar 列来复制该列的前几个字符,然后对其进行排序。这是我的猜测。 (编辑)此外,由于 vendorID 仅在本地建立索引,这可能会导致某种下推排序(我们在我习惯的版本中没有那种东西,但我听说它很漂亮而且可能很慢)
  • @DanielStackenland 即使在我应用排序的所有列上添加索引也不能解决问题。也许我需要在选项或过滤器上设置一些属性。任何帮助表示赞赏。
  • @joshstrike 我不能这样做,因为该数据是从另一个来源导入的。
  • 为什么不能在 GlnCode 上创建包含 ItemNumber、ItemUOM、VendorID 的非聚集索引
  • 你PK怎么这么大,看来RecordIdentifier可能就是PK?

标签: sql-server


【解决方案1】:

您的表索引定义不是最佳的。您也不必创建额外的单个索引,因为它们被非聚集索引覆盖。如下构建索引时,您将获得更好的性能:

表定义:

CREATE TABLE [dbo].[T_GENERIC_ARTICLE]
(
    RecordIdentifier int IDENTITY(1,1) PRIMARY KEY NOT NULL,
    GlnCode nvarchar(100) NOT NULL,
    Description nvarchar(MAX) NOT NULL,
    VendorId nvarchar(100) NOT NULL,
    VendorName nvarchar(100) NOT NULL,
    ItemNumber nvarchar(100) NOT NULL,
    ItemUOM nvarchar(128) NOT NULL
)
GO

CREATE UNIQUE NONCLUSTERED INDEX [UniqueNonClusteredIndex-Composite2]
    ON [dbo].[T_GENERIC_ARTICLE](GlnCode, ItemNumber,ItemUOM,VendorId ASC);

GO

修改后的查询

SELECT TOP (51) 
    [RecordIdentifier] AS [RecordIdentitifer],
    [GlnCode] AS [GlnCode], 
    [VendorId] AS [VendorId], 
    [ItemNumber] AS [ItemNumber], 
    [ItemUOM] AS [ItemUOM],      
    [Description] AS [Description], 
    [VendorName] AS [VendorName]
    FROM [dbo].[T_GENERIC_ARTICLE]
    ORDER BY [GlnCode], [ItemNumber], [ItemUOM], [VendorId] 

首先将在主键上执行键查找,然后是非聚集索引扫描。这是您希望完成大部分工作的地方。

参考: Indexes in SQL Server

希望对你有帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-29
    相关资源
    最近更新 更多