2

我写了一个INSERT/SELECT非常有效的疯狂声明,除了我认为如果我可以避免使用LEN([stats].[dbo].[Domain].[DomainName])两次,它可以再调整一点。现在运行需要 20 秒,如果我LEN用实际数字替换这些部分进行测试,实际上需要一秒钟,因此我希望!

我一直在绞尽脑汁想如何将它变成一个变量,这样我就可以使用它两次,但只有一次性能受到影响。我在 SQL Server 2008 R2 上物有所值。

非常感谢!

INSERT INTO [stats].[dbo].[5MinStats] (Qty, MsgRequest, MsgRecType, MsgDateTime, DomainID)
   SELECT
      COUNT([stats].[dbo].[RawMsgLog].[MsgRequest]) AS Qty, 
      [stats].[dbo].[RawMsgLog].[MsgRequest], 
      [stats].[dbo].[RawMsgLog].[MsgRecType], 
      DATEADD(minute, DATEDIFF(minute, 0, [stats].[dbo].[RawMsgLog].[MsgDateTime])/ 5 * 5, 0) AS MsgDateTime, 
      [stats].[dbo].[Domain].[DomainID] 
   FROM 
      [stats].[dbo].[RawMsgLog], [stats].[dbo].[Domain]
   WHERE 
      RIGHT([stats].[dbo].[Domain].[DomainName], LEN([stats].[dbo].[Domain].[DomainName])) = RIGHT([stats].[dbo].[RawMsgLog].[MsgRequest], LEN([stats].[dbo].[Domain].[DomainName]))
      AND [stats].[dbo].[RawMsgLog].[switch] = 1
   GROUP BY 
      [stats].[dbo].[RawMsgLog].[MsgRequest], 
      [stats].[dbo].[RawMsgLog].[MsgRecType], 
      DATEADD(minute, DATEDIFF(minute, 0, [stats].[dbo].[RawMsgLog].[MsgDateTime]) / 5 * 5, 0), 
      [stats].[dbo].[Domain].[DomainID]
   ORDER BY 
      MsgDateTime ASC
4

3 回答 3

3

将您更改WHERE为以下内容:

WHERE stats.dbo.Domain.DomainName LIKE '%' + stats.dbo.RawMsgLog.MsgRequest

这避免了RIGHT()andLEN()函数,并允许您的查询使用任何可用的索引......将函数应用于索引列将混淆它们并导致使用扫描。

我还会做一些其他的改变......

  1. 别名你的表。
  2. []不需要的话不要用...
  3. 使用显式JOIN.

这会给你以下查询:

INSERT INTO stats.dbo.5MinStats (
    Qty, 
    MsgRequest, 
    MsgRecType, 
    MsgDateTime, 
    DomainID
)
SELECT 
    COUNT(rml.MsgRequest) as Qty, 
    rml.MsgRequest, 
    rml.MsgRecType, 
    DATEADD(minute, 
      DATEDIFF(minute, 0, rml.MsgDateTime)/ 5 * 5, 0) as MsgDateTime, 
    d.DomainID 
FROM 
    stats.dbo.RawMsgLog rml
    JOIN stats.dbo.Domain d
        ON d.DomainName LIKE '%' + rml.MsgRequest
WHERE rml.switch=1
GROUP BY 
    rml.MsgRequest, 
    rml.MsgRecType, 
    dateadd(minute, datediff(minute, 0, rml.MsgDateTime)/ 5 * 5, 0), 
    d.DomainID
ORDER BY MsgDateTime ASC
于 2013-03-25T22:40:15.060 回答
0

您可以使用它CHARINDEX来加快速度:

WHERE CHARINDEX([stats].[dbo].[Domain].[DomainName], [stats].[dbo].[RawMsgLog].[MsgRequest]) > 0

DomainName如果在列中的任何位置找到 in的值,这将返回 true MsgRequest

于 2013-03-25T22:46:09.593 回答
0

在你的条件的前半部分,你做了一个“正确”,子字符串的长度与字段本身的长度相同(即 right(field, len(field))。你可以删除它并只使用该字段然后,您的比较可以是通配符文本:

WHERE stats.dbo.RawMsgLog.MsgRequest like '%' + stats.dbo.Domain.DomainName

你也可以使用这个子字符串比较,但我想它会更慢。

right(stats.dbo.RawMsgLog.MsgRequest, LEN(stats.dbo.Domain.DomainName)) = stats.dbo.Domain.DomainName
于 2013-03-25T22:59:08.240 回答