【问题标题】:Optimising a SQL query which is taking a long time to execute优化执行时间较长的 SQL 查询
【发布时间】:2012-04-30 08:18:15
【问题描述】:

我有一个简单的数据库,我想做一个简单的查询。

这些是我的数据库表的列:

  • external_id
  • 时间戳
  • 价值
  • 验证
  • 原因
  • 基准
  • 你的
  • 黄花菜

这些列是:

  • external_id是某个meter的id
  • Timestamp 什么都不做
  • Value 是那个仪表的值
  • Validation 只是是或否
  • Reason 刚刚得到了一个 varchar 值,这是有原因的
  • Datum 是日期
  • Uur 是那个小时
  • Afronden 是四舍五入所需的列

我要执行的查询的目标是获取每天值总和的最高值和最低值。

如您所见,每一天都以小时为单位,必须检查或数据是否相同或发生变化并由此获得总值。

这是我的查询:

Declare @totaal bigInt
Declare @tussentotaal bigint
Declare @Datum varchar
Declare @datumverschil varchar
Declare @hoogste bigint
Declare @laagste bigint
Declare @teller bigint
Declare @tellettotaal bigint

set @tellettotaal = (select count(*) from cresent_opdracht_de_proost_wim.dbo.[test])

Set @teller = 1

SET @datum = (Select top(1) datum 
              from cresent_opdracht_de_proost_wim.dbo.[test] 
              order by afronden asc)

Set @datumverschil = @Datum
set @tussentotaal = 0
set @totaal = 0
set @hoogste = 1775000006856
set @laagste = 1775000006856

while @teller <= @tellettotaal
begin
  if @teller = 1
  Begin
    set @tussentotaal = (select top(1) value 
                         from cresent_opdracht_de_proost_wim.dbo.[test] 
                         order by afronden asc)

    if @tussentotaal != 0
    begin
      Set @tussentotaal = @tussentotaal/100
    end
  End
  Else
  begin
    SET @tussentotaal = (Select top(1) value 
                         from (select top (@teller) * 
                               from cresent_opdracht_de_proost_wim.dbo.[test]) q 
                         order by afronden desc)

    Set @tussentotaal = @tussentotaal/100
  end

  if @tussentotaal != 0 
  Begin
    Set @totaal = @totaal + @tussentotaal
  end

  SET @teller= @teller + 1

  Set @datumverschil = (Select top(1) datum 
                        from (select top (@teller) * 
                              from cresent_opdracht_de_proost_wim.dbo.[test]) q 
                        order by afronden desc)

  if @datum != @datumverschil
  Begin
    if @totaal >= @hoogste
    begin
      set @hoogste = @totaal
    end

    if @totaal <= @laagste
    begin
      if @totaal != 0
      Begin
        set @laagste = @totaal
      end
    end

    Set @datum = @datumverschil
    set @totaal = 0
    select @teller As teller
  end
end

Select @hoogste As hoogste
Select @laagste As laagste

After 22 分钟后,仅处理了 44000 行。

有人知道如何优化我的查询吗?

【问题讨论】:

  • 显示创建该数据库和表的 MySQL。特别是,显示您拥有的索引。
  • 最好发布示例数据和所需结果,这样我们就不必先弄清楚您的 RBAR 代码在做什么。答案可能是以基于集合的方式重写它。还有什么版本的 SQL Server?
  • 我最初想插入图片,但我的声誉不够好,所以我将它们上传到互联网上。我的数据库是由 csv 创建的,这就是数据库的样子
  • 嗯...你知道“min()”和“max()”函数吗?
  • 您按afronden 排序,您是否在该列上创建了索引?除了索引之外,您还可以尝试使用 min()max() 函数,而不是使用带有排序的 top(1)

标签: performance sql-server-2012


【解决方案1】:

嗯,有没有想过不使用破碎的程序方法可能是一个想法?

首先,你的逻辑可能被打破了——时间听起来太大了,所以也许你只是有一个死循环。抱歉,大多数人很难理解边缘语言 - 即任何不是英语的东西,所以你的表格和字段名称没有意义。不理解的人几乎无法调试废话。

那说:我认为您可以通过不在顶部 1 上运行无意义的循环来总共减少很多查询 - 而是让所有内容按降序排列。残酷地说:摆脱循环并制作一个编译结果集的语句。严重地。这应该是可能的。不要像 20 年前许多人在 dbase 时代所做的那样,试图超越查询优化器并返回编写过程数据库代码。一般来说。您的查询是线性的,这意味着没有并行化,您对条件的微观管理意味着没有查询优化器可以做聪明的事情(因为优化是逐个语句的)。在一个语句中定义结果集,您可能想知道它的效率如何。

我很确定最后你会发现你基本上是在尝试比你编写查询更好的东西。使用 SQL - 定义结果集。

最后,在不知道您的数据分布和 - 哎哟 - 索引的情况下 - 我们真的帮不上忙。也许您只是错过了任何合理的索引?谁知道——你什么都不告诉我们(没有查询计划输出,没有表定义,没有索引定义)。

它也可能不必滥用数据类型:Declare @Datum varchar - OUCH。听说过 sql server 中的 DATE 数据类型吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 2021-03-13
    • 2019-04-16
    • 2012-11-09
    相关资源
    最近更新 更多