2

私はすべてを見てきましたが、これを処理するためのインテリジェントな方法をまだ見つけていませんが、可能であると確信しています:

履歴データの 1 つのテーブルには、四半期ごとの情報が含まれています。

CREATE TABLE Quarterly (
unique_ID INT UNSIGNED NOT NULL,
date_posted DATE NOT NULL,
datasource TINYINT UNSIGNED NOT NULL,
data FLOAT NOT NULL,
PRIMARY KEY (unique_ID));

履歴データの別のテーブル (非常に大きい) には、毎日の情報が含まれています。

CREATE TABLE Daily (
unique_ID INT UNSIGNED NOT NULL,
date_posted DATE NOT NULL,
datasource TINYINT UNSIGNED NOT NULL,
data FLOAT NOT NULL,
qtr_ID INT UNSIGNED,
PRIMARY KEY (unique_ID));

qtr_ID フィールドは、データベースに入力された日次データのフィードの一部ではありません。代わりに、Daily テーブルの qtr_ID フィールドに、Quarterly.unique_ID 行 ID をさかのぼって入力する必要があります。そのデータ ソースのその Daily.date_posted。

たとえば、四半期データが

101 2009 年 3 月 31 日 1 4.5
102 2009 年 6 月 30 日 1 4.4
103 2009 年 3 月 31 日 2 7.6
104 2009 年 6 月 30 日 2 7.7
105 2009 年 9 月 30 日 1 4.7

そして毎日のデータは

1001 2009-07-14 1 3.5 ??
1002 2009-07-15 1 3.4 &&
1003 2009-07-14 2 2.3 ^^

次に、??が必要です。qtr_ID フィールドには、その日付のそのデータ ソースの最新の四半期として '102' が割り当てられ、&& も '102' になり、^^ は '104' になります。

課題には、両方のテーブル (特に日次テーブル) が実際には非常に大きいこと、繰り返しの日付を取り除くために正規化できないこと、または別の方法で最適化することができないこと、および特定の日次エントリでは先行する四半期ごとのエントリがないことが含まれます。

datediff (課題はゼロより大きい datediff の最小値を見つけることです) を使用してさまざまな結合を試みましたが、何も機能していません - 通常、私の構文はどこかで壊れています。どんなアイデアでも大歓迎です。基本的なアイデアやコンセプトを実行し、報告します。

4

3 に答える 3

1

次のようなものを使用して、四半期 ID のサブクエリを実行するだけです。

(
 SELECT unique_ID 
 FROM Quarterly 
 WHERE 
     datasource = ? 
     AND date_posted >= ? 
 ORDER BY
     unique_ID ASC
 LIMIT 1
)

もちろん、これでは最高のパフォーマンスが得られない可能性があり、日付が四半期ごとに順次追加されることを前提としています (そうでない場合order by date_posted)。ただし、問題は解決するはずです。

このサブクエリをINSERTorUPDATEステートメントでテーブルのqtr_IDフィールドの値として使用しますDaily

于 2010-05-14T20:42:54.147 に答える
0

このクエリでさらに作業を行った後、元のコンセプトよりもパフォーマンスが大幅に向上しました。最も重要な改善は、Daily と Quarterly の両方のテーブルにインデックスを作成することでした。Daily では (datasource, date_posted) と (date_posted, datasource) USING BTREE と (datasource) USING HASH でインデックスを作成し、Quarterly では同じことを行いました。もの。これはやり過ぎですが、クエリ エンジンが使用できるオプションがあることを確認しました。これにより、クエリ時間が以前の 1% 未満に短縮されました。(!!)

次に、特定の状況では、ORDER BY と LIMIT の代わりに MAX() を使用できることを知ったので、MAX() の呼び出しを使用して適切な unique_ID を取得します。これにより、クエリ時間が約 20% 短縮されました。

最後に、InnoDB ストレージ エンジンを使用すると、更新する Daily テーブルのチャンクを任意の 1 つのクエリでセグメント化できることを知りました。これにより、多少の手間とスクリプトを使用してクエリをマルチスレッド化できるようになりました。並列処理はうまく機能し、すべてのスレッドでクエリ時間が直線的に短縮されました。

したがって、最初の試行よりも文字通り 1000 倍優れたパフォーマンスを発揮する基本的なクエリは次のとおりです。

UPDATE Daily
SET qtr_ID =
(
  SELECT MAX(unique_ID)
  FROM Quarterly
  WHERE Daily.datasource = Quarterly.datasource AND
        Daily.date_posted > Quarterly.dateposted
)
WHERE unique_ID > ScriptVarLowerBound AND
      unique_ID <= ScriptVarHigherBound
;
于 2010-05-31T21:29:25.170 に答える
0

以下は意図したとおりに動作しているように見えますが、確かに醜いです (同じ DATEDIFF への呼び出しが 3 回あります!!)。おそらく、動作中のクエリを確認することで、誰かがそれをさらに削減または改善できる可能性があります。

UPDATE Daily SET qtr_ID = (select unique_ID from Quarterly
WHERE Quarterly.datasource = Daily.datasource AND
DATEDIFF(Daily.date_posted, Quarterly.date_posted) = 
(SELECT MIN(DATEDIFF(Daily.date_posted, Quarterly.date_posted)) from Quarterly
WHERE Quarterly.datasource = Daily.datasource AND
DATEDIFF(Daily.date_posted, Quarterly.date_posted) > 0));
于 2010-05-17T21:01:26.080 に答える