2

簡単なクエリを実行したい単純なデータベースがあります。

これらは私のデータベーステーブルの列です:

  • external_id
  • タイムスタンプ
  • 価値
  • 検証
  • 理由
  • データム
  • ウル
  • アフロンデン

列は次のとおりです。

  • external_id特定のメーターのIDです
  • Timestamp何もしません
  • Valueはそのメーターの値です
  • Validationはいまたはいいえです
  • Reasonvarchar理由のある値を取得しました
  • 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

22 分後、44000 行のみが処理されました。

クエリを最適化する方法を知っている人はいますか?

4

1 に答える 1

1

うーん、壊れた手続き型アプローチを使用しないのはアイデアかもしれないと思ったことはありますか?

まず、ロジックが壊れている可能性があります。時間が長すぎるため、デッドループが発生している可能性があります。申し訳ありませんが、ほとんどの人がフリンジ言語を理解するのは非常に困難です。つまり、英語以外のものはすべて、テーブル名とフィールド名は意味がありません。ナンセンスは、それを理解していない人々によってほとんどデバッグ可能ではありません。

つまり、トップ1で無意味なループを実行しないことで、合計でクエリを大幅に減らすことができると思います。代わりに、すべてを降順で並べ替えます。残酷に言えば、ループを取り除き、結果セットをコンパイルする1つのステートメントを作成します。真剣に。それは可能であるはずです。多くの人が20年前のdbaseの時代に行ったように、クエリオプティマイザの裏をかいて、手続き型データベースコードの記述に戻ってはいけません。一般に。クエリは線形です。つまり、並列化は行われず、条件のマイクロ管理は、クエリオプティマイザが賢明なことを実行できないことを意味します(最適化はステートメントごとであるため)。結果セットを1つのステートメントで定義すると、それがどれほど効率的か疑問に思うかもしれません。

最後に、クエリを書くよりも優れたものを基本的に上手くやろうとしていることがわかると確信しています。SQLを使用-結果セットを定義します。

そして最後に、あなたのデータ分布と-痛い-インデックス-を知らなければ、私たちは本当に助けることはできません。たぶん、あなたは単に賢明なインデックスを見逃していますか?誰が知っていますか-あなたは私たちに何も言わないでください(クエリプランの出力、テーブルの定義、インデックスの定義はありません)。

また、データ型を悪用する必要がない可能性もあります。@Datumvarchar-OUCHを宣言します。SQLサーバーのDATEデータ型について聞いたことがありますか?

于 2012-04-30T08:48:27.090 に答える