Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么尽管已排序的列已被索引,但我的SQL Server排序仍然很慢?_Sql_Sql Server_Sql Server 2005_Linq To Entities - Fatal编程技术网

为什么尽管已排序的列已被索引,但我的SQL Server排序仍然很慢?

为什么尽管已排序的列已被索引,但我的SQL Server排序仍然很慢?,sql,sql-server,sql-server-2005,linq-to-entities,Sql,Sql Server,Sql Server 2005,Linq To Entities,我有一个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.positionTy

我有一个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,查询将对列进行索引,这无助于加快排序速度

如果您想使查询速度更快,请颠倒表的顺序。具体地说,在联接的表中,首先列出表
country


这之所以有帮助,是因为where子句可以过滤第一个表中的行,而不必进行所有这些连接,然后过滤行。

聚集索引中的字段的顺序是什么?您需要将
startDateTime
字段放在第一位,以便
order BY
匹配,或者在本例中,
(countryId,startDateTime)
按该顺序放在前面,因为您需要选择单个
countryId
(间接地,通过
countryName
)然后按
startDateTime

排序如果您的查询在此之前不包含订单,则它将以找到的任何顺序返回数据。无法保证再次运行查询时,数据将以相同的顺序返回

当包含ORDERBY子句时,dabatase必须按照正确的顺序构建行列表,然后按照该顺序返回数据。这可能需要大量额外的处理,转化为额外的时间

对查询可能返回的大量列进行排序可能需要更长的时间。在某个时刻,缓冲区空间将耗尽,数据库将不得不开始交换,性能将下降


尝试返回较少的列(指定所需的列,而不是选择*),然后查看查询是否运行得更快。

您也应该尝试下面的代码

将记录插入到临时表中,而不使用Order by子句

SELECT * into #temp 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'
Select * from #temp ORDER BY startDatetime
现在使用ORDERBY子句运行语句

SELECT * into #temp 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'
Select * from #temp ORDER BY startDatetime

因为您的查询投影所有列(
*
),它需要5列作为联接条件,并且在可能的联接表列上有一个unselective
WHERE
子句,这会导致查询命中:优化器决定扫描整个表的成本较低,对其进行筛选和排序,以便对索引进行范围扫描,然后查找表中的每个键以检索所需的额外列(5个用于联接,其余用于
*

部分覆盖此查询的更好索引可以是:

CREATE INDEX ... ON .. (countryId, startDatetime);

Jeffrey建议使用聚集索引将100%覆盖查询,并肯定会提高性能,但更改聚集索引有许多副作用。我将从如上所述的非聚集索引开始。除非其他查询需要它们,否则您可以删除您创建的所有其他非聚集索引,它们不会帮助此查询。

索引不是按排序顺序存储的吗?添加时,我在“排序:升序”和“排序:降序”之间有一个选项。我在SQLite中使用了索引,使ORDER BY查询更快。我交换了连接的顺序,并将查询时间从16秒减少到了7秒,但order BY仍然占用了所有7秒的时间。乔治:索引是按排序顺序存储的,是的,但通常每个表只能选择一个索引,在这种情况下,它选择聚集索引
PK\u jobs
,因为它是一个覆盖索引。如果有更紧迫的问题,比如连接,索引的存在对排序没有帮助。我已经在我的第一个聚集索引中对列进行了重新排序,使countryId是第一个,startDateTime是第二个,并且只在countryId和startDateTime上添加了一个单独的索引。看看我的查询计划,查询似乎击中了Join to表上的PK索引和我的'employees'表上的PK,但没有击中其他任何东西(也没有击中我的聚集索引)。速度没有提高。但您应该注意,聚集索引中的列也会添加到该表中每个非聚集索引的每个条目中,并且如果聚集索引变得臃肿,例如由多个大列组成,然后整个表的索引结构就会膨胀,从而严重影响整体性能。如果可能的话,我会尽量避免使用复合聚集键,而且最肯定的是,我会不惜一切代价避免VARCHAR列长度大于等于10个字符。@marc_s:是的,就是这样-我的描述字段太大了(索引太麻烦了)。感谢heaps提供的帮助。这运行得快多了——整个查询需要很多时间——我不确定这是否真的有帮助——起初看起来这让事情变得更快了,但是:SELECT*into#temp FROM[atr].[dbo].[jobs]不起作用——“列名必须是唯一的”(多个“id”列),所以我尝试了:SELECT title,cityName,stateName进入#temp。。。这很快(我的假设是,该列非常大,它会将每一行的大小向上推,从而使总数据大小向上推,因此ORDER BY需要对大量数据进行排序—太多,无法放入内存,因此我们点击磁盘并最终进行分页/交换/抖动/其他操作。您加入的所有外键列是否也都已索引??@marc_s:是的,独立表上的所有ID列也都被索引。我99.9%确定不是连接速度慢,因为删除ORDER BY(并离开连接)将时间从~16秒减少到远小于1秒。因此我认为这是“正确”的答案-我的描述列非常大(它存储了一大块HTML),这会将每行的大小向上推,这意味着排序必须转到磁盘。+1,因为列太多。您应该首先返回