4

おい。次の表とデータを検討してください...

in_timestamp | out_timestamp | name  | in_id | out_id | in_server | out_server | status
timestamp1   | timestamp2    | data1 |id1   | id2    | others-server1   | my-server1 | success
timestamp2   | timestamp3    | data1 | id2   | id3    | my-server1   | my-server2 | success
timestamp3   | timestamp4    | data1 | id3   | id4    | my-server2   | my-server3 | success
timestamp4   | timestamp5    | data1 | id4   | id5    | my-server3   | others-server2 | success
  • 上記のデータは、サーバー間での一部のデータの実行フローのログを表しています。
  • たとえば、一部のデータが「outside-server1」から一連の「my-servers」に流れ、最終的に宛先の「others-server2」に流れました。

質問 :

1) このログを表現可能な形式でクライアントに提供する必要があります。クライアントは、一連の「my-servers」について何も知る必要はありません。私が提供することになっているのは、インフラストラクチャに入力されたデータのタイムスタンプと、それが離れたときのタイムスタンプだけです。次の情報にドリルダウンします。

in_timestamp (of 'others_server1' to 'my-server1')
out_timestamp (of 'my-server3' to 'others-server2')
name 
status

同じようにSQLを書きたい!誰か助けてくれませんか?注 : 常に 3 つの「my-servers」があるとは限りません。それは状況によって異なります。たとえば、data2 などに 4 つの「my-server」が関係している可能性があります。

2) SQL に代わるものはありますか? 私はストアドプロシージャ/などを意味しますか?

3) 最適化? (レコードの数は膨大です! 現在、1 日あたり約 500 万件です。最大 1 週間前のレコードを表示することになっています。)

事前に、助けてくれてありがとう!:)

4

4 に答える 4

2
WITH RECURSIVE foo AS
        (
        SELECT  *, in_timestamp AS timestamp1, 1 AS hop, ARRAY[in_id] AS hops
        FROM    log_parsing.log_of_sent_mails
        WHERE   in_server = 'other-server1'
        UNION ALL
        SELECT  t_alias2.*, foo.timestamp1, foo.hop + 1, hops || in_id
        FROM    foo
        JOIN    log_parsing.log_of_sent_mails t_alias2
        ON      t_alias2.in_id = (foo.t_alias1).out_id 
        )
SELECT  *
FROM    foo
ORDER BY
        hop DESC
LIMIT 1
于 2010-04-08T11:58:51.633 に答える
1

テーブルには階層構造 (隣接リスト) があります。これは、再帰 CTE を使用して PostgreSQL v8.4 以降で効率的にクエリできます。Quassnoiは、実装方法についてブログ投稿を書いています。作成する必要があるのは非常に複雑なクエリですが、彼は必要なものと非常によく似た例でそれをよく説明しています. 特に彼の最後の例を見ると、配列を使用して最初のノードから最後のノードまでの完全なパスを取得するクエリを示しています。

于 2010-04-05T13:22:27.803 に答える
0
  • @その他の読者:

    最初にMarkByersによって投稿された最初の回答を参照してください。回答にコメントしている間は利用できないテーブル/リンクなどを使用する必要があったため、彼の投稿に「コメント」するのではなく「回答」を使用しました。:)

  • @マークバイアーズ:

リンクをありがとう...それは本当に私を助けました、そして私はサーバー間のパスを生成する方法を理解することができました...私が何ができたかを見てください。

in_id   | in_timestamp  | out_timestmap | name  | hops_count    | path  |
id1     | timestamp1    | timestamp2    | data1 | 1             | {id1} |
id2     | timestamp2    | timestamp3    | data1 | 2             | {id1,id2} |
id3     | timestamp3    | timestamp4    | data1 | 3             | {id1,id2,id3} |
id4     | timestamp4    | timestamp2    | data1 | 4             | {id1,id2,id3,id4} |

*パスは「in_id」を使用して生成されます

次のクエリを使用しました...

WITH RECURSIVE foo AS
        (
        SELECT  t_alias1, 1 AS hops_count, ARRAY[in_id] AS hops
        FROM    log_parsing.log_of_sent_mails t_alias1
        WHERE   in_server = 'other-server1'
        UNION ALL
        SELECT  t_alias2, foo.hops_count + 1 AS hops_count, hops || in_id
        FROM    foo
        JOIN    log_parsing.log_of_sent_mails t_alias2
        ON      t_alias2.in_id = (foo.t_alias1).out_id 
        )
SELECT  (foo.t_alias1).in_id,
        (foo.t_alias1).name,
        (foo.t_alias1).in_timestamp,
        hops_count,
        hops::VARCHAR AS path
FROM    foo   ORDER BY   hops

しかし、私はまだ究極の段階に到達することができませんでした。これが私が最終的に手に入れたいものです...

in_id   | in_timestamp  | out_timestmap | name  | hops_count    | path  |
id4     | timestamp1    | timestamp5    | data1 | 4             | {id1,id2,id3,id4}|

*タイムスタンプを確認します。クライアントに内部インフラストラクチャについて知られたくないので、これが必要です。したがって、彼にとって重要なのは、timestamp1とtimestamp5の間のタイムラグです。

どれだけ私がそれを達成できるかについての手がかりはありますか?

ps私もQuassnoiに連絡してみます。:)

于 2010-04-08T11:31:28.267 に答える
0

それを行う 1 つの方法- データが安定している場合 (たとえば、挿入時に変更されない)、挿入時に推移的な関係をオンザフライで計算することです (たとえば、トリガーを介して、または挿入を行うアプリによって)。

たとえば、テーブルに新しい列「start_ts」があります。レコードを挿入すると:

in_timestamp | out_timestamp | name  | in_id | out_id | in_server | out_server | status
timestamp3   | timestamp4    | data1 | id3   | id4    | my-server2   | my-server3 | success

...その後、ロジックはレコードを自動的に検索name=data1し、新しく挿入されたレコードにout_id=id3複製します。start_tsこれらの推移的な値をどのように計算するかによっては、最終ステータスの伝播に関して特別なロジックが必要になる場合があります。

name=data1ところで、必ずしも前の (およびout_id=id3) レコードを検索する必要はありませんstart_ts。処理中にデータ レコードのメタ データ自体の値を保持できます。

次に、最終的なレポートは単純ですselect start_ts, out_ts from T where out_server=others_server2(もちろん、out_server と status に関してはより複雑ですが、それでも単一の単純な選択です)。

2 番目のオプションはもちろん、結果のレポートを計算するより単純なループです。方法がわからない場合は、SQL BFS 実装の google または「スタック」(現在は動詞として受け入れられていますか?) を使用します。

于 2010-04-05T11:16:54.080 に答える