我正在从C#MVC应用程序中对SQL数据库执行以下两个查询。
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
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)
答案 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上,这可能需要一段时间,因为数据可能必须进行物理重新排序。因此,在没有活动用户的维护期间执行此操作。