【问题标题】:slow SQL command慢 SQL 命令
【发布时间】:2010-04-15 00:02:10
【问题描述】:

我需要从一个表中获取一些数据(并在途中扩展一些 XML)并将其放入另一个表中。由于源表可能有数千条或导致超时的记录,我决定分批执行 100 条记录。该代码按计划运行,因此分批执行对客户来说可以。如果我在源数据库中有 200 条记录,则存储过程运行得非常快,但如果有数千条记录,则需要几分钟。我猜“TOP 100”只有在通过所有记录后才进入前100名。我需要在某个时候更改整个代码和 sproc,因为它无法扩展,但现在有快速修复方法可以让它运行得更快吗?

INSERT INTO [deviceManager].[TransactionLogStores] 
SELECT TOP 100 [EventId],
    [message].value('(/interface/mac)[1]', 'nvarchar(100)') AS mac,
    [message].value('(/interface/device) [1]', 'nvarchar(100)') AS device_type,
    [message].value('(/interface/id) [1]', 'nvarchar(100)') AS device_id,
    [message].value('substring(string((/interface/id)[1]), 1, 6)', 'nvarchar(100)') AS store_id,
    [message].value('(/interface/terminal/unit)[1]', 'nvarchar(100)') AS unit,
    [message].value('(/interface/terminal/trans/event)[1]', 'nvarchar(100)') AS event_id,
    [message].value('(/interface/terminal/trans/data)[1]', 'nvarchar(100)') AS event_data,
    [message].value('substring(string((/interface/terminal/trans/data)[1]), 9, 11)', 'nvarchar(100)') AS badge,
    [message].value('(/interface/terminal/trans/time)[1]', 'nvarchar(100)') AS terminal_time,
    MessageRecievedAt_UTC AS db_time
FROM [deviceManager].[TransactionLog]
WHERE EventId > @EventId
--WHERE MessageRecievedAt_UTC > @StartTime AND MessageRecievedAt_UTC < @EndTime
ORDER BY terminal_time DESC 

【问题讨论】:

  • EventId 是否在 TransactionLog 表中建立索引?

标签: sql sql-server


【解决方案1】:

您需要 ORDER BY 吗?如果数据未排序,则 TOP 不需要将整个结果集取回前 100 名。如果您确实需要 order by,请确保您在 terminal_time 上有一个索引;如果花了那么长时间,你可能没有。

另外,请确保您在 EventID 上有一个索引。

【讨论】:

  • +1 用于订购。不过,不确定您是否可以在 XPath 表达式上创建索引(可以吗?)。
  • @Tomalak 好点!我没有注意到它是一个 XPath 表达式,而不是一个标准列。 Retrocoder——这就是为什么随着表变大需要花费很长时间来选择的原因。因为 ORDER BY 是一个 XPath 表达式,服务器必须评估整个结果集,包括为每一行执行 XPath,然后才能对数据进行排序(从而找出您的 which TOP 100想要。)如果不能去掉ORDER BY,可以用表中的真实列来排序吗?
  • 显然,您可以在 SQL Server (msdn.microsoft.com/en-us/library/ms191497.aspx) 中拥有 XML 索引。
  • 酷!我不认为你可以,我上次看的时候,但我只是每隔一两年就在 SQL Server 中研究 XML 的东西。 (我经常使用 XML,我也经常使用 SQL,但在不同的舞台上......)所以,是的,如果可以的话,删除 ORDER BY,然后获取您订购/过滤的项目的一些索引,生活应该是美好的。
【解决方案2】:

您在EventId(和MessageRecievedAt_UTC)上有索引吗?

@EventId@StartTime/@EndTime 是否与各自的列具有相同的数据类型?

【讨论】:

    【解决方案3】:

    看起来(如果我错了,请纠正我,这是其他构造)message.value() 是一个始终采用相同输入的 UDF。您每 N 行调用该函数大约 10 次——这肯定会成为性能负担。如果这是一个确定性函数(我希望是),您可以将各种函数调用的结果缓存到临时表中,性能应该会显着提高。

    如果做不到这一点,可能是排序花费的时间最长。它必须先获得完整的结果集,然后才能决定如何排序。正如 Matt 指出的那样,索引可以大大加快这一进程。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-09
      • 2021-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多