【问题标题】:Sql Query Taking longer to execute than expected timeSql Query 执行时间比预期时间长
【发布时间】:2012-04-03 12:51:54
【问题描述】:

我正在尝试执行下面的查询,但大约需要 40 分钟。

select logentryid 
from (
     select * from logentry_payloaddata pd,
     logentry le
     where (
            pd.entryid=le.logentryid
       and
            le.eventdatetime=(trunc(sysdate) - 14)
     )
     order by le.logentryid asc
)

在表 logentry 中有 4,24,91,461 条记录,在 logentry 有效负载数据中有 4,15,16,346 条记录(在世界某些地区或“42,491,461”和“41,516,346”,甚至“42.491.461”和“41.516.346”在其他一些部分——Ed.)

在相应的表中有logentryid和entryid的索引。

有人可以建议在这种情况下该怎么做。

【问题讨论】:

  • 在 eventdatetime 创建索引?
  • 这是导致问题的 eventdatetime 过滤器。我不确定这是什么 RDBMS,但您可能无法使用索引,因为您正在与函数的输出进行比较。
  • 也重写。看起来像不必要的嵌套选择。您可能会受益于仅使用 le 的最后 14 天作为子选择,然后将其加入到 pd 中。
  • @Lamak:如果每个表中只有那么几条记录,我认为查询可能不会花费 40 分钟。
  • 实际上,我认为这是印度对 Lakh 的常见用法(参见此处:en.wikipedia.org/wiki/Lakh)。我会将问题编辑为 good 'ole 'Merican

标签: sql


【解决方案1】:

一些建议:

1 - 索引eventdatetime(如果还没有)

2 - 为 (trunc(sysdate) - 14) 定义一个变量 - 这将阻止函数对每一行运行,并允许使用步骤 1 中的索引

3 - 取消混淆您的代码。这里不需要嵌套,您使用的是旧式 JOIN 语法,这可能会导致问题:

SELECT logentryid 
FROM logentry_payloaddata pd
INNER JOIN logentry le
   ON pd.entryid=le.logentryid
WHERE le.eventdatetime = @MyDateVariable
ORDER BY logentryid ASC

【讨论】:

  • 你为什么建议这个变量?什么环境会在每一行重新计算这个标量常数? (除非您的意思是隐式转换可能会导致问题,其中转换不只是显式转换标量常量工作?)
【解决方案2】:
SELECT
  le.logentryid
FROM
  logentry_payloaddata     pd
INNER JOIN
  logentry                 le
    ON pd.entryid=le.logentryid
WHERE
  le.eventdatetime = CAST(trunc(sysdate) - 14 AS DATETIME)
ORDER BY
  le.logentryid ASC

1)。为我的利益更改了布局(使用 INNER JOIN 等),但怀疑它会改变性能。

2)。在您的日期比较中添加了CAST()。您的代码需要隐式 CAST() 任何方式。使用 explicit CAST() 确保正在转换常量,而不是数据字段。这很重要,因为它决定了如何使用或不能使用任何索引。

3)。索引 - 没有单一的答案,这取决于您的数据统计。

logentry_payloaddata 表上,您肯定需要entryid 上的索引。

logentry 表上有两个不同的索引可能会有所帮助:
- (logentryid, eventdatetime)
- (eventdatetime, logentryid)

我的最佳猜测是后者将提供最佳性能。但我建议同时创建两者并检查实际使用的。

【讨论】:

  • 非常感谢您的回复:-)
【解决方案3】:

试试:

select logentryid  
from logentry_payloaddata pd
inner join logentry le on pd.entryid=le.logentryid and le.eventdatetime=(trunc(sysdate) - 14)

您可以将 where 子句放在内部连接上以便更快地进行比较。

如果您的数据库同时被多个客户端访问/更新,也值得尝试使用 nolock。请先阅读有关使用 nolock 的信息 - 在其他客户端执行提交之前获得结果。

【讨论】:

  • 您基于什么“将 where 子句放在内部连接上以便更快地比较”?它将在所有版本的 SQL Server 中生成相同的执行计划,并且只是混淆了过滤器的实际应用位置
  • 我认为这只适用于子查询。您不同意布尔比较 'pd.entryid=le.logentryid' 与 'le.eventdatetime=(trunc(sysdate) - 14)' 一样多的过滤器并且应该在同一个地方(where 子句或内部连接)。
  • 不,pd.entryid=le.logentryid 是 JOIN CRITERIA,eventdatetime 过滤器应用于连接的结果集,应该在 where 子句中。
  • @user923721 - SQL 被编译为计划,而不是“按原样”执行。 JOIN, 版本实际上会产生相同的计划。在这种情况下,在ON 子句和WHERE 子句之间移动条件完全没有区别。您甚至可以加入ON le.eventdatetime=(trunc(sysdate) - 14) 并使用WHERE pd.entryid=le.logentryid 进行过滤,然后仍然获得相同的计划。 SQL 编译器不会简单到让他们感到困惑。
  • JNK 是一回事。 “此连接的连接条件是 id 匹配且日期 =whatever” 连接条件同样可以为空(完全外部连接),然后您应用 id 匹配过滤器和 date=whatever
猜你喜欢
  • 2018-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-13
  • 2012-03-30
  • 2019-04-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多