我有一个SQL查询(由LINQ to Entities生成),大致类似于以下内容:
SELECT * FROM [mydb].[dbo].[employees] JOIN [mydb].[dbo].[industry] ON jobs.industryId = industry.id JOIN [mydb].[dbo].[state] ON jobs.stateId = state.id JOIN [mydb].[dbo].[positionType] ON jobs.positionTypeId = positionType.id JOIN [mydb].[dbo].[payPer] ON jobs.salaryPerId = payPer.id JOIN [mydb].[dbo].[country] ON jobs.countryId = country.id WHERE countryName = 'US' ORDER BY startDatetime
该查询返回大约1200行,我认为这不是一个很大的行。不幸的是,这也需要约16秒。如果没有ORDER BY,查询将花费不到1秒的时间。
我已经使用SQL Server Management Studio在startDatetime列上添加了索引,还在“ cityId,industryId,startDatetime,positionTypeId,payPerId,stateId”(即我们在“作业”中使用的所有列)上创建了聚集索引。联接和在列上我们使用ORDER BY on)。我已经在JOIN中使用的每个列上都有单独的索引。不幸的是,这并没有使查询更快。
我运行了一个展示计划,并得到:
|--Nested Loops(Inner Join, OUTER REFERENCES:([mydb].[dbo].[jobs].[cityId])) |--Nested Loops(Inner Join, OUTER REFERENCES:([mydb].[dbo].[jobs].[stateId])) | |--Nested Loops(Inner Join, OUTER REFERENCES:([mydb].[dbo].[jobs].[industryId])) | | |--Nested Loops(Inner Join, OUTER REFERENCES:([mydb].[dbo].[jobs].[positionTypeId])) | | | |--Nested Loops(Inner Join, OUTER REFERENCES:([mydb].[dbo].[jobs].[salaryPerId])) | | | | |--Sort(ORDER BY:([mydb].[dbo].[jobs].[issueDatetime] ASC)) | | | | | |--Hash Match(Inner Join, HASH:([mydb].[dbo].[currency].[id])=([mydb].[dbo].[jobs].[salaryCurrencyId])) | | | | | |--Index Scan(OBJECT:([mydb].[dbo].[currency].[IX_currency])) | | | | | |--Nested Loops(Inner Join, WHERE:([mydb].[dbo].[jobs].[countryId]=[mydb].[dbo].[country].[id])) | | | | | |--Index Seek(OBJECT:([mydb].[dbo].[country].[IX_country]), SEEK:([mydb].[dbo].[country].[countryName]='US') ORDERED FORWARD) | | | | | |--Clustered Index Scan(OBJECT:([mydb].[dbo].[jobs].[PK_jobs])) | | | | |--Clustered Index Seek(OBJECT:([mydb].[dbo].[payPer].[PK_payPer]), SEEK:([mydb].[dbo].[payPer].[id]=[mydb].[dbo].[jobs].[salaryPerId]) ORDERED FORWARD) | | | |--Clustered Index Seek(OBJECT:([mydb].[dbo].[positionType].[PK_positionType]), SEEK:([mydb].[dbo].[positionType].[id]=[mydb].[dbo].[jobs].[positionTypeId]) ORDERED FORWARD) | | |--Clustered Index Seek(OBJECT:([mydb].[dbo].[industry].[PK_industry]), SEEK:([mydb].[dbo].[industry].[id]=[mydb].[dbo].[jobs].[industryId]) ORDERED FORWARD) | |--Clustered Index Seek(OBJECT:([mydb].[dbo].[state].[PK_state]), SEEK:([mydb].[dbo].[state].[id]=[mydb].[dbo].[jobs].[stateId]) ORDERED FORWARD) |--Clustered Index Seek(OBJECT:([mydb].[dbo].[city].[PK_city]), SEEK:([mydb].[dbo].[city].[id]=[mydb].[dbo].[jobs].[cityId]) ORDERED FORWARD)
重要的一行似乎是“ | –Sort(ORDER BY:([mydb]。[dbo]。[jobs]。[issueDatetime] ASC)))” ―在该列上未提及任何索引。
为什么我的ORDER BY使查询变慢得多,如何加快查询速度?
如果您的查询之前不包含订单,则它将以找到的顺序返回数据。不能保证再次运行查询时,数据甚至会以相同的顺序返回。
当您包含order by子句时,dabatase必须按正确的顺序构建行列表,然后按该顺序返回数据。这可能需要大量额外的处理,从而转化为额外的时间。
对大量列进行排序可能需要更长的时间,您的查询可能正在返回这些列。在某些时候,您将耗尽缓冲区空间,并且数据库将必须开始交换,并且性能将下降。
尝试返回较少的列(指定所需的列而不是Select *),并查看查询是否运行得更快。