我有一个数据库表,大约有325万行.对于简单的查询,我的查询速度非常慢,我不认为我在try 做任何疯狂的事情.我基本上没有数据库优化方面的知识,所以希望这是一个简单的解决方案.

该表保存合同数据记录,包括金额、日期和一些与其他表(VendorIdAgencyIdStateId)相关的ID,这是数据库表:

CREATE TABLE [dbo].[VendorContracts]
(
    [Id] [uniqueidentifier] NOT NULL,   
    [ContractDate] [datetime2](7) NOT NULL,
    [ContractAmount] [decimal](19, 4) NULL, 
    [VendorId] [uniqueidentifier] NOT NULL,
    [AgencyId] [uniqueidentifier] NOT NULL,
    [StateId] [uniqueidentifier] NOT NULL,

    [CreatedBy] [nvarchar](max) NULL,
    [CreatedDate] [datetime2](7) NOT NULL,
    [LastModifiedBy] [nvarchar](max) NULL,
    [LastModifiedDate] [datetime2](7) NULL,
    [IsActive] [bit] NOT NULL,

    CONSTRAINT [PK_VendorContracts] 
        PRIMARY KEY CLUSTERED ([Id] ASC)
                WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
                      OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

我在数据库中有这3个索引.我没有创建这些,看起来像是Entity Framework Core通过迁移自动创建的,所以它们可能是错误的.

CREATE NONCLUSTERED INDEX [IX_VendorContracts_AgencyId] 
ON [dbo].[VendorContracts] ([AgencyId] ASC)
         WITH (STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = OFF, 
               ONLINE = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]

CREATE NONCLUSTERED INDEX [IX_VendorContracts_StateId] 
ON [dbo].[VendorContracts] ([StateId] ASC)
         WITH (STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = OFF, 
               ONLINE = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]

CREATE NONCLUSTERED INDEX [IX_VendorContracts_VendorId] 
ON [dbo].[VendorContracts] ([VendorId] ASC)
         WITH (STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = OFF, 
               ONLINE = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]

我在我的网站上有一个页面,我希望用户能够 Select 一个供应商,并查看按州划分的合同金额总额.

我有一个疑问:

SELECT SUM(ContractAmount), StateId
FROM [dbo].[VendorContracts]
WHERE VendorId = '...'
GROUP BY StateId

但这需要很长时间,比如15-20分钟.

我try 了其他更简单的查询,我想可能总和让一切都变慢了,但这些速度也令人难以置信.我try 按供应商和州查询:

SELECT *
FROM [dbo].[VendorContracts]
WHERE VendorId = '...' AND StateId = '...'

尽管它只返回几千行,但仍然需要很长的时间.

enter image description here

enter image description here

奇怪的是,我有另一个数据库在一个单独的服务器上,有一个类似的表,有大约600万条记录,它根本没有这样的问题.我可以在不到一两秒钟的时间内运行SUM查询和其他查询.而且那个数据库表有相同的索引,所以不确定为什么那个表如此高效,而这个表不是.

在过go 的一周里,我每天都插入数十万条记录,我重新组织了索引,但这并没有解决问题,我还需要做些什么来优化它吗?我的数据库在Azure上,我是否需要更改或增加一些设置?

推荐答案

问题是索引不支持查询.换句话说:服务器不能只使用一个索引为您的查询提供服务,因此它要么必须对每一行进行键查找,要么更可能 Select 只扫描整个表.

一般来说,正是由于这个原因,单列索引不是很有用.可以更改现有索引之一.

  • 您希望WHERE中的equality =谓词成为索引键中的第一列.
  • 然后添加联接列和分组列.在此阶段,通常只值得添加其中一个,除非联接位于唯一值上.
  • 最后,添加所有其他列.这些不必是键的一部分,它们可以是INCLUDE列.

例如:

CREATE NONCLUSTERED INDEX [IX_VendorContracts_VendorId] ON [dbo].[VendorContracts]
  (VendorId, StateId)
INCLUDE
  (ContractAmount)
WITH (DROP_EXISTING = ON, ONLINE = ON);

Sql相关问答推荐

我可以将INSERT语句与SELECT一起使用来创建条件吗?

删除MariaDB数据库中的JSON数据

在SQL中使用类别值将行转置为列

为什么TRY_CONVERT返回一个XML验证错误而不是NULL?

PostgreSQL:按小时查看调整日期

如何将我的联接数据放入每个用户每月多行的列中?

根据Rails活动记录中时间戳/日期时间的时间部分从PostgreSQL中提取记录

将一个数组反嵌套到另外两个数组SQL中(Athena/presto)

使用拆分器将已分组的不同值连接在一起

如何在SQL中从多个查询进行分组

使用多个WITH子查询的替代方法

使用特定的Order By子句随机化SQL输出

用另一个表中的特定名称替换 SQL 查询中的 ID.但我的两个表都有多个列

使用 XML 作为 SQL 表

如何使用 Google BigQuery 中的条件根据特定列值连接列的 N 行?

创建具有多个子查询的 SQL 视图

更新之前如何获得价值

根据开始时间和结束时间计算has_impact字段

如何在 RavenDB Studio (RQL) 中插入更新文档

PostgreSQL 中的递归树查询