简体   繁体   English

SQL索引表联接

[英]SQL Index Table Join

I am executing the following two queries against a SQL database from within my C# MVC application. 我正在C#MVC应用程序中对SQL数据库执行以下两个查询。

Query1 查询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 查询2

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

Upon running the method that executes these queries each query hangs and oftentimes the next page of my application will not load for over a minute or it will time out on one or the other. 运行执行这些查询的方法时,每个查询都会挂起,并且通常情况下,我的应用程序的下一页将不会加载一分钟以上,否则将在另一个页面上超时。 When I run the same queries in SQL Server each of them take between 10 and 15 seconds to run which is still too long. 当我在SQL Server中运行相同的查询时,它们中的每个查询都需要10到15秒钟才能运行,但仍然太长。

How can I speed them up? 我如何加快速度? Ive never created a SQL index and Im not sure how to create it for each of these or if thats the right path to pursue. 我从未创建过SQL索引,我不确定如何为每个索引创建索引,或者那是否是正确的方法。

Tableone currently has 20808805 rows and 3 columns, tabletwo has 597707 rows and 6 columns. 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)

Firstly, as @ Robert Co said, a index on tabletwo.name will help on performance. 首先,正如@ Robert Co所说,tabletwo.name上的索引将有助于提高性能。

Also, are there indexes on tableone.id and tabletwo.id? 另外,tableone.id和tabletwo.id上是否有索引? I will asume there are, given they look like primary keys. 假设它们看起来像主键,我会假设有。 If not, you definitely need to put indexes on them. 如果没有,您肯定需要在它们上放置索引。 I can see tableone to tabletwo is a many-to-one relation, which means you probably don't have a primary key on table one. 我可以看到tableone与tabletwo是多对一的关系,这意味着您可能在表1上没有主键。 You seriously need to add a primary key on tableone, such as tableoneid, and make it a clustered index! 您非常需要在tableone上添加主键(例如tableoneid),并使其成为聚集索引!

I think another reason here is, your tableone is much bigger than tabletwo which is limited down even further by the where clause(name = 'Name'). 我认为这里的另一个原因是,您的tableone比tabletwo大得多,后者受到where子句(name ='Name')的限制。 This means you are joining a large table (tableone) to a small table (tabletwo with the where clause). 这意味着您正在将一个大表(tableone)连接到一个小表(tablewhere中带有where子句的表)。 In SQL, join large table to a small table is going to be slow. 在SQL中,将大表连接到小表将很慢。

The solution that I can think about is, maybe you can move some columns, such as 'type', to tableone, so that you can limit tableone into a small set in your query as well : 我可以考虑的解决方案是,也许您可​​以将诸如“类型”之类的某些列移至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 + "'"

I am not quite sure how these suggestions fitted into your data model, I just hope they may help. 我不太确定这些建议如何适合您的数据模型,我只是希望它们会有所帮助。

10 to 15 seconds with 20 million rows and no index? 10到15秒有2000万行并且没有索引? That's not bad! 不错!

As Ethen Li says it's all about indexes. 正如Ethen Li所说,这全都与索引有关。 In an ideal world you would create indexes on all columns that feature in a filter (JOINs and WHEREs) or ORDER BYs. 在理想情况下,您将在具有过滤器(JOIN和WHERE)或ORDER BY的所有列上创建索引。 However, as this could severely impact UPDATEs and INSERTs you need to be more practical and less ideal. 但是,由于这可能会严重影响UPDATE和INSERT,因此您需要更实际,更不理想。 With the information you have provided I would suggest creating the following indexes: CREATE INDEX index1 ON tableone (name); 根据您提供的信息,我建议创建以下索引:CREATE INDEX index1 ON tableone(名称); If tableone.id is your candidate key (that which uniquely identifies the row) you should also create an index on it - possibly clustered, it depends how ID is generated): 如果tableone.id是您的候选键(用于唯一标识行的键),则还应该在其上创建索引-可能是聚簇的,这取决于ID的生成方式):

CREATE UNIQUE INDEX IX1TableOne ON tableone (id); CREATE UNIQUE INDEX IX1TableOne ON tableone(id);

Or 要么

CREATE UNIQUE CLUSTERED INDEX IX1TableOne ON tableone (id); 在tableone(id)上创建唯一的聚集索引IX1TableOne;

For tabletwo: the same applies to ID as for tableone - create at least a unqiue index on ID. 对于表two:与表one同样适用于ID-在ID上至少创建一个无索引的索引。

With these indexes in-place you should find a significant performance improvement. 有了这些索引,您应该发现性能上的显着提高。

Alternatively to add primary key constraints: 或者添加主键约束:

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

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

On tableone this might take a while because the data might have to be physically re-ordered. 在tableone上,这可能需要一段时间,因为可能必须对数据进行物理重新排序。 Therefore, do it during a maintenance period when there are no active users. 因此,请在没有活动用户的维护期间执行此操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM