I have a database table with about 3.5 million records. The table holds contract data records, with an amount, a date, and some IDs related to other tables (VendorId, AgencyId, StateId), this is the database table:
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]
I have a page on my site where I'd like users to be able to select a vendor, and see the total amount of contract amounts, split by state.
I have this query:
SELECT SUM(ContractAmount), StateId
FROM [dbo].[VendorContracts]
WHERE VendorId = '...'
GROUP BY StateId
And I created this index to help with that:
CREATE NONCLUSTERED INDEX [IX_VendorContracts_VendorId] ON [dbo].[VendorContracts]
(
[VendorId] ASC
)
INCLUDE([Id],[StateId],[ContractAmount],[ContractDate],[AgencyId])
WITH (STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = OFF, ONLINE = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF)
This works great for most my vendors, I can get results back fairly quickly in a second or two. But there are a couple vendors that each have about 1 million records though, and those take quite a while, usually a few minutes.
So I was wondering if there's any way to optimize further, by modifying my index? Or any other way?
Or am I maybe going about this wrong? Not sure if running such huge SUM queries on 1 million records is just not a great way to do this. Records aren't added very frequently to this table, we maybe add a few thousand once or twice a month, so I was thinking of maybe having a nightly process that would grab the SUM data and store them in a separate table, and then query that when I need to run reports.