SQL'ORDER BY'缓慢

时间:2009-04-01 20:03:07

标签: database sql-server-2005

ORDER BY通常很慢吗?我正在尝试运行一些sql语句,其中WHERE子句非常简单,但我正在ORDER BY索引列上尝试VARCHAR(50)

出于显示原因,我需要按字母顺序排序。我认为让数据库为我做这个是最有效的。

此时,我正在寻找

  • 优化sql查询
  • 对代码
  • 中的结果集进行排序

以下是我尝试运行的实际查询:

// B.SYNTAX is a TEXT/CLOB field
// Indexes on NAME, MODULENAME. PREVIOUS is a CHAR(1) with no index
"SELECT A.NAME, B.SYNTAX, B.DESCRIPTION, A.RATE1, A.RATE2, 
A.RATE3, A.STARTDATE, A.ENDDATE, A.HIDE, A.CATEGORYNAME 
FROM A, B WHERE A.MODULENAME='"+loadedModuleName+"' 
AND A.NAME = B.NAME AND (A.PREVIOUS<>'N' OR A.PREVIOUS IS NULL) 
ORDER BY A.NAME"

表A的大小约为2000行,B约为500行。

我可能还应该提到,由于我们支持多个数据库,因此无法进行太多特定于数据库的优化。此外,该应用程序部署在客户站点。

我期待返回数百条记录(少于1000条)。

你会做什么?任何提示都表示赞赏。感谢。

14 个答案:

答案 0 :(得分:8)

在索引字段上排序应该慢,因为它可以按索引顺序提取数据。您可能希望提供有关数据库结构(DDL)和实际查询的信息,以便人们可以查看。

你绝对应该尽可能使用SQL排序而不是代码排序,这样你才能在那里走上正轨。

<强>更新 好的,一些事情。首先,您不应该使用“+ loadedModuleName +”构造,因为它使每个查询都是唯一的并且搞砸了优化器。使用参数。其次,你的Order by子句是否是表A或B是不明确的 - 明确表示并选择带有索引的表(即使两者都有索引,使其显式)。最后,您的“上一个”字段仍然可以作为char(1)进行索引。我会做所有事情,但最后建议的索引,测试速度,如果仍然很慢,去索引并再次检查。

更新因此,您将返回&lt; 1000条记录,但该表的总大小是多少?

更新哦,伙计,对不起我之前没有抓到这个。如果要在SQL Server上正确部署它,则查询应为:

SELECT A.NAME, B.SYNTAX, B.DESCRIPTION, A.RATE1, A.RATE2, A.RATE3, A.STARTDATE, A.ENDDATE, A.HIDE, A.CATEGORYNAME 
FROM Table1 A join Table2 B on (A.Name=B.Name)
WHERE (A.MODULENAME=@ModuleName) AND (A.PREVIOUS<>'N' OR A.PREVIOUS IS NULL) 
ORDER BY A.NAME

试试这个,我几乎可以保证你会看到一个巨大的加速。

答案 1 :(得分:6)

只要数据库可以找到与ORDER BY表达式对应的索引,

ORDER BY通常不会很慢。

但是,您的SQL语句可能包含强制数据库在返回结果之前扫描整个表的其他内容,例如SELECT TOP n

答案 2 :(得分:3)

如果您的过滤器如下所示:

WHERE col1 = @value1
      AND col2 = @value2
      AND col3 = @value3
ORDER BY
      col4

,然后您需要在(col1, col2, col3, col4)上创建索引。

优化器将使用索引来过滤前三个值并按顺序排序。

如果您没有这样的索引,则会发生以下情况之一:

  1. 优化程序将使用索引来过滤WHERE条件,但仍需要ORDER个剩余行。
  2. 优化程序将使用索引ORDER值,但需要查看所有值以将其过滤掉。
  3. 优化器根本不会使用索引,因此需要查看2“所有值以及过滤掉它们”和“1”所有剩余行必须进行排序“是真的。

答案 3 :(得分:2)

更新:作为您发布的查询,我认为最好的选择是将查询视为良好,因为:

  • 几行,不关心谁做这项工作。然后更容易使用ORDER BY
  • 对于很多行,不要让客户端完成工作:RDMBS更专业,确保服务器有更多的内存和CPU。

您必须考虑的订单提示是:

  • ORDER BY是对SQL查询进行保修排序的 ONLY 方式。
  • 排序中的最佳 工作人员在任何情况下都是数据库:请确保这一点!
  • 尽量减少返回行的基数。
  • 根据查询创建索引。这意味着将有序列放在索引的最后。
  • 如果查询速度很快,请避免编制索引。
  • 您可以考虑对索引进行排序,然后如果您只对表进行排序并具有良好的索引,则排序的成本可能接近于零。

有关索引的更多经验法则,请查找this other SO question

答案 4 :(得分:1)

它不应该慢。优化您的查询和数据库结构(至少索引和statistcs,如果它是SQL Server)。除了ORDER BY之外,你的查询中还有其他一些东西会导致这种缓慢吗?

SELECT A.NAME, B.SYNTAX, B.DESCRIPTION, A.RATE1, A.RATE2, A.RATE3,
       A.STARTDATE, A.ENDDATE, A.HIDE, A.CATEGORYNAME
FROM Table1 A JOIN Table2 B on A.Name = B.Name
WHERE A.MODULENAME = @ModuleName AND A.PREVIOUS<>'N' OR A.PREVIOUS IS NULL
ORDER BY A.NAME

选项1

如果您只查询几个简单的列(2-4),也可以将它们包含在索引中。这样您的查询将运行得更快。还要确保该索引列上的排序顺序与查询中的排序顺序相匹配。

// if your query looks like this:
SELECT [Name], [Title], [Count] ORDER BY [COUNT]

// you can create an index on [Name], [Title], [Count]

选项3

创建view并将其绑定到schema。然后查询view

中的数据

选项3

如果你使用SQL Server 2005和obove,你也可以尝试在 SQL Server Profiler 中运行查询,它会向你推荐你可以应用于你的最佳索引和统计数据表,以优化此特定查询的性能。

选项4

尝试重建索引和统计信息。

选项5

您可以尝试将索引/表放入不同硬盘上的单独文件组中。

答案 5 :(得分:1)

如果要选择足够少的行来显示,除非您限制使用ORDER BY或{{1返回的行数,否则LIMIT子句将花费任何可察觉的时间量是不可想象的。 }}

我们需要更多信息。什么dbms?查询计划是什么样的?你有没有TOP查看查询计划?你看到了什么不同?


编辑:

ORDER BY

SELECT A.NAME, B.SYNTAX, B.DESCRIPTION, A.RATE1, A.RATE2, A.RATE3, A.STARTDATE, A.ENDDATE, A.HIDE, A.CATEGORYNAME FROM A, B WHERE A.MODULENAME='"+loadedModuleName+"' AND A.NAME = B.NAME AND (A.PREVIOUS<>'N' OR A.PREVIOUS IS NULL) ORDER BY NAME NAME吗? primary key上有index吗?单独或与其他领域?按什么顺序?
一个loadedModuleName返回多少行?
我怀疑“NAME尝试使用A.PREVIOUS <> 'N' OR A.PREVIOUS IS NULL"慢,这是我认为是等效的,可能会有所帮助。
使用和不使用(NOT A.PREVIOUS = 'N')对查询计时,并查看时间是否完全不同。它不应该是。

<小时/> 编辑:

如果ORDER BYNAMEA不唯一,那么当B每个A.NAME实例交叉连接时,您的联接将会部分弹道}}。如果50 A行匹配且50 B行匹配,则最终会得到2500个结果行,这可能不是您想要的。

答案 6 :(得分:1)

ORDER BY并不是特别慢,特别是如果该列上有索引。特别是,如果该列上有聚簇索引,则数据已经排序。

您还可以使用分页(TOPROW_NUMBER)等来提供帮助。

答案 7 :(得分:1)

请记住,许多查询编辑器只会在前50个左右从数据库返回后显示结果。

添加ORDER BY将强制它在数据库上等待所有结果,这将显示查询的实际速度。

在这些情况下,原始查询和ORDERed查询速度相同;你只是被骗了,认为第一个很快,因为你的编辑很快得到前50行左右。

答案 8 :(得分:1)

昨晚我在一个更生产类型的数据库(不是开发人员)上做了一些性能测试,这是我发现的:

表A中的总行数:13000

表B中的总行数:5000

连接查询返回的行:5000

使用ORDER BY子句所花费的时间:~5.422秒

不使用ORDER BY子句所花费的时间:~5.345秒。

所以看起来ORDER BY并没有太大的区别。 (我可以添加几毫秒)。

我还通过将所有B.SYNTAX值设置为NULL来测试,以确保它不仅仅是传输如此多数据的网络延迟。

现在我从SELECT子句中删除了B.SYNTAX,查询只花了0.8秒!

所以似乎整个CLOB列都是瓶颈。这并不意味着我已经获得了使查询更快的解决方案,但至少我不会花时间编写排序算法。

感谢所有回复的人。我学到了很多东西,这让我尝试了一些不同的东西。

答案 9 :(得分:0)

说“顺序”本身是缓慢的,这不公平。您有许多RDBM要考虑他们自己的实现,以及数据类型和索引方案。但是,我会怀疑你可以在服务器上以更快的速度对客户端进行排序,但这并不是说在服务器上对它进行排序是正确的。

答案 10 :(得分:0)

这里有一些很多的问题。

就纯粹的性能而言,假设像索引一样正确设置,数据库非常擅长排序。 对于一个隔离的查询,在数据库中排序可能是最快的。

不幸的是,在实践中,数据库经常成为应用程序的瓶颈。您可以采取任何措施将工作从数据库移开,这将提高您的整体应用程序吞吐量。这包括将排序操作移动到不太繁忙的业务,Web或表示层。表示层可能无法有效地对一个查询进行排序,但它可能更适合处理整体负载。当您可以将这项工作一直可靠地推送到各个最终用户计算机时,尤其如此,尽管这可能会有问题。

另一方面,这里需要考虑的还有纯粹的表现。您还想考虑未来的维护。什么比简单的“ORDER BY”条款更易于维护?这只是一行代码,相比之下谁知道有多少额外的程序员可以在别处工作。这可能是一个案例,你最好在问题上投入一些钱,以确保你的数据库能够保持可接受的级别的性能,排序等等。

即使在这里,问题也没有被切割和干燥。有一种思想流派认为排序确实应该被视为表示层的功能,并且最终表示层也是更易于维护的工作场所。我不同意这个理论,但它就在那里。

答案 11 :(得分:0)

ORDER BY强制RDBMS排序。

排序需要您的RDBMS服务器上可能不存在的资源。

在某些情况下(即单表查询),您可以编写与索引匹配的ORDER BY - 如果您的RDBMS保证表以索引顺序保存 - 则可能为零成本。 [通过丢弃RDBMS和使用文件,可以进一步改进依赖于大量单表查询的数据库设计。]

通常,ORDER BY必须排序。

“我认为让数据库为我做这件事是最有效的。”

这个假设是错误的。数据库不一定比数据库外的程序更有效。

答案 12 :(得分:0)

在客户端上排序,在我看来是你不应该做的事情。数据库引擎针对数据排序进行了优化。

与其他人说的一样,如果你可以限制你选择的行数,这将会运行得更快。

回答以下问题可能会有所帮助:

  • 返回的行数 查询?
  • 正在选择多少列?
  • 你加入任何牌桌吗?
  • 有/无需多长时间 ORDER BY?

答案 13 :(得分:0)

这里有很多非常好的建议,但有一件小事我没看到我想评论。

您使用的数据库是什么?作为一个花费大量时间在MySQL上的人,跳出来的东西是OR语句。使用OR,MySQL可能真的愚蠢。我已经看到做两个选择并将它们联合起来会更快。

如果您的行数很大(在表中,未返回)可能是一个因素。

否则我同意其他帖子。索引应该让它变得快速,让数据库做它而不是自己处理它通常会更好。 DB知道它在做什么。除非你有一个非常大的数据集并希望将排序负担转移到客户端(因此数据库可以进行更多查询),否则我会让数据库进行排序工作。