2

私はしばらくの間、この問題について頭を悩ませていましたが、助けを求めることにしました。温度/湿度チャート レコーダー データ (現在 775,000 レコード以上) を保持するテーブルがあり、そこから統計クエリを実行しようとしています。問題は、これに 2 分ほどかかることが多く、まったく戻ってこないこともあり、プログラムを強制的に閉じなければならない (Control-Alt-Delete) ことです。最初はそれほど問題はありませんでした。500k レコードという魔法のマークに到達した後で初めて、深刻な速度低下が発生し始め、より多くのデータがコンパイルされてテーブルにインポートされるにつれて、次第に悪化しました。

クエリ (パススルー) は次のとおりです。

SELECT dbo.tblRecorderLogs.strAreaAssigned, Min(dbo.tblRecorderLogs.datDateRecorded) AS FirstRecorderDate, Max(dbo.tblRecorderLogs.datDateRecorded) AS LastRecordedDate,
Round(Avg(dbo.tblRecorderLogs.intTempCelsius),2) AS AverageTempC,
Round(Avg(dbo.tblRecorderLogs.intRHRecorded),2) AS AverageRH,
Count(dbo.tblRecorderLogs.strAreaAssigned) AS Records
FROM dbo.tblRecorderLogs
GROUP BY dbo.tblRecorderLogs.strAreaAssigned
ORDER BY dbo.tblRecorderLogs.strAreaAssigned;

チャート データが格納されるテーブル構造は次のとおりです。

idRecorderDataID     Number     Primary Key
datDateEntered       Date/Time  (indexed, duplicates OK)
datTimeEntered       Date/Time
intTempCelcius       Number
intDewPointCelcius   Number
intWetBulbCelcius    Number
intMixingGPP         Number
intRHRecorded        Number
strAssetRecorder     Text       (indexed, duplicates OK)
strAreaAssigned      Text       (indexed, duplicates OK)

開始日と終了日だけでなく、割り当てられたエリアに基づいてこのテーブルからデータを取得できるようにするプログラムを作成しようとしています。私が現在所有しているデータセットのサイズでは、この種のレポートは処理するには大きすぎて (どうやら)、マシンが回答を返すことはありません。このテーブルを処理するすべてのクエリで、ODBC タイムアウトをほぼ 180 秒に延長する必要がありましたが、これは単純にサイズの問題です。人々が何かを持っているなら、私はいくつかの深刻な助けを使うことができます. 前もって感謝します!

-- 2012 年 8 月 13 日 @ 1050 時間に編集 --

IT 部門が問題のマシンを制御し、誰かがリモート管理コンソールを使用してフルタイムでログインしているため、SQL Server でクエリをテストできませんでした。パフォーマンスの問題の影響を軽減するための暫定的な手順を試みましたが、この問題に対する恒久的な解決策を探しています。

中間ステップ:

dbo.tblRecorderLogs SQL Server テーブルの構造をミラーリングするローカル テーブルを作成しました。これに対して、以前の SELECT ステートメントをサブクエリとして使用して INSERT INTO を実行しました。その後の統計分析は、この「一時的な」ローカル テーブルから行われます。プロセスが完了すると、ローカル テーブルは切り捨てられます。

-- 2012 年 8 月 13 日 @ 1217 時間に編集 --

表示されているクエリを SQL Server 管理コンソールで実行しました。コンソールが提供するクエリ タイマーによると、完了までに 1 分 38 秒かかりました。

-- 2012 年 8 月 15 日 @ 1531 時間を編集 --

次のコードを使用して、VBA DoCmd.RunSQL ステートメントとしてクエリを実行し、一時テーブルにデータを入力しようとしました。

INSERT INTO tblTempRecorderDataStatsByArea ( strAreaAssigned, datFirstRecord, 
datLastRecord, intAveTempC, intAveRH, intRecordCount )
SELECT dbo_tblRecorderLogs.strAreaAssigned, Min(dbo_tblRecorderLogs.datDateRecorded) 
AS MinOfdatDateRecorded, Max(dbo_tblRecorderLogs.datDateRecorded) AS MaxOfdatDateRecorded, 
Round(Avg(dbo_tblRecorderLogs.intTempCelsius),2) AS AveTempC, 
Round(Avg(dbo_tblRecorderLogs.intRHRecorded),2) AS AveRHRecorded, 
Count(dbo_tblRecorderLogs.strAreaAssigned) AS CountOfstrAreaAssigned FROM 
dbo_tblRecorderLogs GROUP BY dbo_tblRecorderLogs.strAreaAssigned ORDER BY 
dbo_tblRecorderLogs.strAreaAssigned

コードが実行されると問題が発生し、クエリに非常に時間がかかります.終了する前にタイムアウトが発生します. これを修正するための「魔法の弾丸」をまだ望んでいます...

-- 2012 年 8 月 20 日 @ 1241 時間に編集 --

私が見つけた唯一の「準」解決策は、失敗したクエリを繰り返し実行することです(いわば、ポンプをプライミングするようなものです)。これにより、クエリがプログラムによって再度呼び出されたときに、ODBC の前に実際に完了する可能性が相対的に高くなります。 SQL Server ドライバーがタイムアウトします。基本的に、不潔な不潔なハックですが、この問題に対処するためのより良いハックはありません。

  1. サーバー側で動作するビューを作成しようとしましたが、速度は上がりません。
  2. 集計されている適切なフィールドは適切にインデックス化されているため、そこを変更することはできません。
  3. 私は、データベースからユーザーにとってすぐに役立つ情報のみを引き出しています。ここでは「SELECT * madness」は行われていません。

私は、公式には、試してみることができないと思います-アイテムがライブではなく、より良いハードウェアを調達する予算がないため、問題に生のコンピューティング馬力を投入することは別として. これを「回答」として投稿し、9 月 3 日までそのままにしておきます。より良い回答がない場合は、自分の回答を受け入れて敗北を受け入れます。

4

1 に答える 1

0

同じテーブルの複数のフィールドに対して最小/最大関数を実行する必要があった場合、メイン/外部クエリの行でサブクエリとして各列を個別に実行する方が速いことがよくあります。

したがって、クエリは次のようになります。

SELECT rLogs1.strAreaAssigned, rLogs1.FirstRecorderDate, rLogs2.LastRecorderDate, rLog3.AverageTempC, rLogs4.AverageRH, rLogs5.Records
FROM (((
    (SELECT strAreaAssigned, min(datDateRecorded) as FirstRecorderDate FROM dbo.tblRecorderLogs GROUP BY strAreaAssigned) rLogs1
    inner join
    (SELECT strAreaAssigned, Max(datDateRecorded) as LastRecordedDate, FROM dbo.tblRecorderLogs GROUP BY strAreaAssigned) rLogs2
    on rLogs1.strAreaAssigned = rLogs2.strAreaAssigned)
    inner join
    (SELECT strAreaAssigned, Round(Avg(intTempCelsius),2) AS AverageTempC, FROM dbo.tblRecorderLogs GROUP BY strAreaAssigned) rLogs3
    on rLogs1.strAreaAssigned = rLogs3.strAreaAssigned)
    inner join
    (SELECT strAreaAssigned, Round(Avg(intRHRecorded),2) AS AverageRH, FROM dbo.tblRecorderLogs GROUP BY strAreaAssigned) rLogs4
    on rLogs1.strAreaAssigned = rLogs4.strAreaAssigned)
    inner join
    (SELECT strAreaAssigned, Count(strAreaAssigned) AS Records, FROM dbo.tblRecorderLogs GROUP BY strAreaAssigned) rLogs5
    on rLogs1.strAreaAssigned = rLogs5.strAreaAssigned
ORDER BY rLogs1.strAreaAssigned;

クエリと上記のクエリを SQL Server の同じクエリ ウィンドウにコピーし、推定実行プランを実行すると、それらを比較して、どちらがより適切に機能するかを確認できます。

于 2013-12-31T02:35:54.723 に答える