问题描述
我才刚刚开始学习INDEX,听说它可以加快结果,但是我的测试却产生了相反的效果。
有关数据的一些要点:
- 我的公司使用SQL Server,但除此以外,我对此一无所知
- 我只是一名员工,没有任何管理员权限,甚至只能查看某些文件夹
- #TABLE1包含23,000多行,并在1秒内运行
- #TABLE2包含超过310万行,运行时间约为1.5分钟
- 使用联接大约需要1.75到2.5分钟
- 我尝试使用INDEX的过程需要2.5到3或更多
- 此后我将加入更多表,但这两个表实质上是其他所有表的基础
我在下面尝试的查询比我执行普通的JOIN花费的时间更长
IF OBJECT_ID('tempdb..#TABLE1') IS NOT NULL DROP TABLE #TABLE1;
IF OBJECT_ID('tempdb..#TABLE2') IS NOT NULL DROP TABLE #TABLE2;
SELECT
cast(T1.[ID] as varchar(20)) as 'ID',cast(T1.[Division] as int) as 'Division',cast(T1.[Category] as int) as 'Category',cast(T1.[Platform] as int) as 'Platform',cast(T1.[Condition] as tinyint) as 'Condition',cast(T1.[First Received] as date) as 'First Received',cast(T1.[Last Received] as date) as 'Last Received'
INTO #TABLE1
FROM
CompanyTable as T1
WHERE
T1.[Name] = 'Canada'
AND T1.[Division] = '100';
CREATE NONCLUSTERED INDEX IX_TABLE1 ON #TABLE1([ID],[Division],[Category],[Platform]);
SELECT DISTINCT
SE.[Date] as 'Date',SE.[ID] as 'ID',SE.[Division] as 'Division',SE.[Category] as 'Category',SE.[Platform] as 'Platform',sum(SE.[Units]) as 'Units',sum(SE.[Sales]) as 'Sales',sum(SE.[Retail]) as 'Retail',sum(SE.[Cost]) as 'Cost'
INTO #TABLE2
FROM
(SELECT
cast(S1.[Date] as date) as 'Date',cast(S1.[ID] as varchar(20)) as 'ID',cast(S1.[Division] as int) as 'Division',cast(S1.[Category] as int) as 'Category',cast(S1.[Platform] as int) as 'Platform',cast(sum(S1.[Quantity]) * -1 as decimal(38,20)) as 'Units',cast(sum(S1.[Net Amount]) * -1 as decimal(38,20)) as 'Sales',cast(sum(S1.[Cost Amount]) * -1 as decimal(38,20)) as 'Cost',cast(sum(S1.[Price]) as decimal(38,20)) as 'Retail'
FROM
SalesTable1 as S1
WHERE
S1.[Division] = '100'
GROUP BY
S1.[ID],S1.[Date],S1.[Division],S1.[Category],S1.[Platform]
UNION ALL
SELECT
cast(S2.[Date] as date) as 'Date',cast(S2.[ID] as varchar(20)) as 'ID',cast(S2.[Division] as int) as 'Division',cast(S2.[Category] as int) as 'Category',cast(S2.[Platform] as int) as 'Platform',cast(sum(S2.[Quantity]) * -1 as decimal(38,cast(sum(S2.[Net Amount]) * -1 as decimal(38,cast(sum(S2.[Cost Amount]) * -1 as decimal(38,cast(sum(S2.[Price]) as decimal(38,20)) as 'Retail'
FROM
SalesTable2 as S2
WHERE
S2.[Division] = '100'
GROUP BY
S2.[ID],S2.[Date],S2.[Division],S2.[Category],S2.[Platform]
) as T2
GROUP BY
T2.[ID],T2.[Date],T2.[Division],T2.[Category],SE.[Platform]
CREATE NONCLUSTERED INDEX IX_TABLE2 ON #TABLE2([ID],[Platform]);
SELECT *
FROM #TABLE1 as T1
JOIN #TABLE2 as T2 ON T1.[ID] = T2.[ID] AND T1.[Division] = T2.[Division] AND T1.[Category] = T2.[Category] AND T1.[Platform] = T2.[Platform]
DROP INDEX IX_TABLE1 ON #TABLE1;
DROP INDEX IX_TABLE2 ON #TABLE2;
我做错了什么导致它变慢了吗?
解决方法
如下所示在#table1和#table2上创建4个不同的索引,然后运行查询。
CREATE NONCLUSTERED INDEX IX_TABLE1_id ON #TABLE1([ID]);
CREATE NONCLUSTERED INDEX IX_TABLE1_Div ON #TABLE1([Division]);
CREATE NONCLUSTERED INDEX IX_TABLE1_Cat ON #TABLE1([ [Category]);
CREATE NONCLUSTERED INDEX IX_TABLE1_Plt ON #TABLE1([[Platform]);
CREATE NONCLUSTERED INDEX IX_TABLE1_id ON #TABLE2([ID]);
CREATE NONCLUSTERED INDEX IX_TABLE1_Div ON #TABLE2([Division]);
CREATE NONCLUSTERED INDEX IX_TABLE1_Cat ON #TABLE3[ [Category]);
CREATE NONCLUSTERED INDEX IX_TABLE1_Plt ON #TABLE4([[Platform]);
,
您需要在临时表上使用具有唯一值的主键作为CLUSTERED INDEX
。然后,您只需要NONCLUSTERED INDEX
列上的另一个JOIN
。假设ID
中的#TABLE1
是唯一的,请像这样创建索引:
ALTER TABLE #TABLE1 ADD CONSTRAINT PK_TABLE1 PRIMARY KEY CLUSTERED ([ID]);
CREATE NONCLUSTERED INDEX IX_TABLE1 ON #TABLE1([Division],[Category],[Platform]);
#TABLE2
的同上,再次假设ID
ID为唯一:
ALTER TABLE #TABLE2 ADD CONSTRAINT PK_TABLE2 PRIMARY KEY CLUSTERED ([ID]);
CREATE NONCLUSTERED INDEX IX_TABLE2 ON #TABLE2([Division],[Platform]);
但是,如果实际的瓶颈是非临时表,那么这可能无法解决您的性能问题。您应该分别运行脚本的SELECT
部分。如果他们自己表现良好,请尝试使用这些索引。如果不是,那么您需要与您的DBA交流并找出SELECT
运行缓慢的原因。