SQL索引表加入

时间:2013-04-06 20:59:48

标签: c# sql sql-server join

我正在从C#MVC应用程序中对SQL数据库执行以下两个查询。

查询1

SELECT tableone.id, name, time, type, grade, product, element, value
FROM dbo.tableone INNER JOIN dbo.tabletwo ON dbo.tableone.id = dbo.tabletwo.id
Where name = '" + Name + "' Order By tableone.id Asc, element

QUERY2

Select DISTINCT element FROM dbo.tableone
INNER JOIN dbo.tabletwo ON dbo.tableone.id = dbo.tabletwo.id
Where name = '" + Name + "'"

在运行执行这些查询的方法时,每个查询都会挂起,并且我的应用程序的下一页通常不会加载超过一分钟,或者它会在一个或另一个上超时。当我在SQL Server中运行相同的查询时,每个查询需要10到15秒才能运行,这仍然太长。

如何加快速度?我从来没有创建过SQL索引,我不知道如何为每个索引创建它,或者如果这是正确的追求途径。

Tableone目前有20808805行和3列,tabletwo有597707行和6列。

Tableone

id(int, not null)
element(char(9), not null)
value(real, null)

Tabletwo

id(int, not null)
name(char(7), null)
time(datetime, null)
type(char(5), null)
grade(char(4), null)
product(char(14), null)

2 个答案:

答案 0 :(得分:3)

首先,正如@ Robert Co 所说,tabletwo.name上的索引将对性能有所帮助。

另外,tableone.id和tabletwo.id上有索引吗?鉴于它们看起来像主键,我会认为有。如果没有,你肯定需要在它们上面放置索引。我可以看到tableone是一个多对一的关系,这意味着你可能没有第一个表上的主键。 您真的需要在tableone上添加主键,例如tableoneid,并使其成为聚集索引!

我认为另一个原因是,你的tableone比tabletwo大得多,而且还受到where子句(name ='Name')的限制。这意味着您将一个大表(tableone)连接到一个小表(具有where子句的tabletwo)。 在SQL中,将大表连接到一个小表会很慢。

我可以考虑的解决方案是,也许您可​​以将某些列(例如“类型”)移动到tableone,以便您可以将tableone限制为查询中的一小部分

Select DISTINCT element FROM dbo.tableone
INNER JOIN dbo.tabletwo ON dbo.tableone.id = dbo.tabletwo.id
Where tableone.type = 'some type' and name = '" + Name + "'"

我不太确定这些建议如何适合您的数据模型,我希望他们可以提供帮助。

答案 1 :(得分:2)

10到15秒,有20万行,没有索引?那还不错!

正如Ethen Li所说,这完全是关于索引的。在理想的世界中,您将在过滤器(JOIN和WHERE)或ORDER BYs中的所有列上创建索引。但是,由于这可能会严重影响UPDATE和INSERT,因此您需要更加实用且不太理想。根据您提供的信息,我建议您创建以下索引: CREATE INDEX index1 ON tableone(name); 如果tableone.id是您的候选键(唯一标识该行的那个),您还应该在其上创建一个索引 - 可能是聚簇的,它取决于ID的生成方式):

创建UNIQUE INDEX IX1TableOne ON tableone(id);

或者

创建独特的CLUSTERED INDEX IX1TableOne ON tableone(id);

对于tabletwo:同样适用于ID和tableone一样 - 在ID上创建至少一个unqiue索引。

使用这些索引,您应该会发现显着的性能提升。

或者添加主键约束:

ALTER TABLE tableone ADD CONSTRAINT pktableone PRIMARY KEY CLUSTERED(id);

ALTER TABLE tabletwo ADD CONSTRAINT pktabletwo PRIMARY KEY CLUSTERED(id);

在tableone上,这可能需要一段时间,因为数据可能必须进行物理重新排序。因此,在没有活动用户的维护期间执行此操作。