我有一个具有以下定义的表:
CREATE TABLE [dbo].[Transactions]
(
[ID] [varchar](18) NOT NULL,
[TIME_STAMP] [datetime] NOT NULL,
[AMT] [decimal](18, 4) NOT NULL,
[CID] [varchar](90) NOT NULL,
[DEPARTMENT] [varchar](4) NULL,
[SOURCE] [varchar](14) NULL,
PRIMARY KEY NONCLUSTERED
(
[ID] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
该表中有7500万行。不知何故,它占用了20 GB的磁盘空间!
以下2个查询...
SELECT
SUM(AMT)
FROM
Transactions
WHERE
TIME_STAMP >= '2017-11-11 00:00:00' AND
TIME_STAMP < '2017-11-12 00:00:00' AND
DEPARTMENT = 'Shoes' AND
SOURCE = 'Website'
SELECT
COUNT(DISTINCT(CID))
FROM
Transactions
WHERE
TIME_STAMP >= '2017-11-11 00:00:00' AND
TIME_STAMP < '2017-11-12 00:00:00' AND
DEPARTMENT = 'Accessories' AND
SOURCE = 'Mobile'
...每次运行大约需要2分钟!
DEPARTMENT和SOURCE字段的基数较低,它们仅包含几个不同的值。
请告知我该怎么做,需要创建哪些索引以及使用哪些设置来优化这些查询的性能。
谢谢!
答案 0 :(得分:0)
解决此特定查询的最佳方法是按以下顺序组合索引(一个索引具有多列):
尝试将最具有选择性的列放在首位,因此,如果来源的变化量大于部门,则应将其放在第一位。该日期显然会最后一次,因为它将触发索引扫描。
答案 1 :(得分:0)
CREATE INDEX IX_Transactions ON Transactions(TIME_STAMP,DEPARTMENT,SOURCE) INCLUDE(AMT,CID)
答案 2 :(得分:0)
我将使用时间戳,部门和源创建索引。我还将AMT和CID添加为包含的列。这意味着您可以通过读取索引而不必完全访问父表来满足您的两个查询。
CREATE INDEX IX_Transactions ON Transactions(TIME_STAMP,DEPARTMENT,SOURCE) INCLUDE(AMT,CID)
答案 3 :(得分:0)
要考虑的另一种选择是运行执行计划,并查看它是否建议使用索引。在考虑索引时,我会做很多事情,因为我发现执行计划推荐的索引比我认为不错但不直观的索引性能有所提高。