Hadoop:The Definitive Guideで説明されているように、RDBMSは悪いですか?

StackOverflow https://stackoverflow.com/questions/4289079

  •  28-09-2019
  •  | 
  •  

質問

Hadoop:The Definitive Guide by Tom Whiteを読んでいます。第13.6章「HBase vs RDMS」では、多くのデータがある場合、最近の10個のアイテムを入手するなどの簡単なクエリでさえ、PythonとPL/SQLを使用して書き直す必要があると述べました。

彼は例として次のクエリを提供します:

SELECT id, stamp, type FROM streams 
WHERE type IN ('type1','type2','type3','type4',...,'typeN')
ORDER BY stamp DESC LIMIT 10 OFFSET 0;

「RDBMSクエリプランナーは、このクエリを次のように扱います。

MERGE (
  SELECT id, stamp, type FROM streams
    WHERE type = 'type1' ORDER BY stamp DESC,
  ...,
  SELECT id, stamp, type FROM streams
    WHERE type = 'typeK' ORDER BY stamp DESC
) ORDER BY stamp DESC LIMIT 10 OFFSET 0;

ここでの問題は、私たちがトップ10 IDのみを追いかけていることですが、クエリプランナーは実際にマージ全体を実現し、最後に制限します。 ....私たちは実際に、Heaportを実行するカスタムPL/Pythonスクリプトを書くまで行きました。 ...ほとんどすべての場合、これはネイティブSQLの実装とクエリプランナーの戦略を上回りました...

予想される穴あけおよびrepermientalの結果

そのような問題を引き起こすような問題を引き起こすデータセットを想像できませんでした。だから私はこの問題についてしばらくプレイし、次の観察を思いついた:

このようなクエリのパフォーマンスは、O(Klogn)によって制限されます。次のようなものに翻訳できるからです。

SELECT * FROM (
  SELECT id, stamp, type FROM streams
    WHERE type = 'type1' ORDER BY stamp DESC LIMIT 10,
  UNION
  ...,
  SELECT id, stamp, type FROM streams
    WHERE type = 'typeK' ORDER BY stamp DESC LIMIT 10
) t ORDER BY stamp DESC LIMIT 10;

(各クエリの「リミット10」に注意してください。ところで、私は組合を制限して注文することはできないことを知っていますが、読みやすさのためにセレクトをラッピングしました)

各サブクエリは、インデックスo(logn)で正しい郵便を見つけるのと同じ速度で実行し、10項目を返す必要があります。 k時間を繰り返すと、O(klogn)を取得します。

また、クエリプランナーが非常に悪いため、最初のクエリを最適化できない場合でも、PL/Pythonに何も書くことなく、組合とのクエリにいつでも翻訳できます。

計算を再確認するために、9,000,000のテストレコードで満たされた1つのPostgreSQLの上にクエリを実行します。結果は、私の予想の両方のクエリが最初のクエリでは非常に速い100ms、2番目のクエリでは300ms(組合のあるもの)であることを確認しました。

したがって、クエリが9,000,000(logn = 23)のレコードで100msで実行される場合、9,000,000,000(logn = 33)のレコードで140msで実行する必要があります。

質問

  • 上記の推論に欠陥がありますか?
  • PL/Pythonで上記のようなクエリを書き直す必要があるデータセットを想像できますか?
  • そのようなクエリがO(k log n)で機能しない状況を見ますか?
役に立ちましたか?

解決

RDMBSクエリプランナーがそのソリューションをクエリのソリューションに使用するという彼らの主張は、少なくともPostgreSQL 9.0では間違っています。他のプラットフォームについても想像する必要があります。同様のクエリで簡単なテストを行いました。

explain select * from client_attribute where client_attribute_type_code in ('UAG', 'RFR', 'IPA', 'FVD') order by client_attribute_id desc limit 10;

                                                      QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
 Limit  (cost=0.00..0.93 rows=10 width=85)
   ->  Index Scan Backward using client_attribute_pkey on client_attribute  (cost=0.00..15516.47 rows=167234 width=85)
         Filter: (client_attribute_type_code = ANY ('{UAG,RFR,IPA,FVD}'::bpchar[]))
(3 rows)

ここでは、client_attribute_idがインデックス化されているため、必要に応じてインデックスを介して戻ってきて、フィルターを適用し、出力が制限に達したときに停止します。

順序列がインデックス化されていない場合、テーブルスキャンとソートが必要ですが、テーブルスキャンは1つだけです。

explain analyze select * from client_attribute where client_attribute_type_code in ('UAG', 'RFR', 'IPA', 'FVD') order by updated desc limit 10;

                                                              QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=13647.00..13647.03 rows=10 width=85) (actual time=180.961..180.964 rows=10 loops=1)
   ->  Sort  (cost=13647.00..14065.09 rows=167234 width=85) (actual time=180.960..180.961 rows=10 loops=1)
         Sort Key: updated
         Sort Method:  top-N heapsort  Memory: 26kB
         ->  Seq Scan on client_attribute  (cost=0.00..10033.14 rows=167234 width=85) (actual time=0.010..106.791 rows=208325 loops=1)
               Filter: (client_attribute_type_code = ANY ('{UAG,RFR,IPA,FVD}'::bpchar[]))

これは、Sequential Scanのコースを通じて上位10の結果を維持するためにHeapsortを使用します。これは、自分が書いたソリューションとまったく同じように聞こえます。

他のヒント

トム・ホワイトは、リレーショナルデータベースが「悪い」と言っているとは思わない。これらは、非関連性のない非セットベースのデータに最適ではありません。

深いオブジェクトグラフがリレーショナルデータベースに十分に役立たないことは長い間知られています。それらは通常、アセンブリが部品のアセンブリのアセンブリで構成されている幾何学データのCAD表現のような問題に見られます。実際、参照チェーンは非常に長いです。

オブジェクトとグラフのデータベースは、90年代前半にそれらを認識していたため、そのような問題の解決策となっています。

リレーショナルデータベースは、リレーショナル、セットベースのデータにとって素晴らしいものです。しかし、すべてのデータはそのカテゴリに分類されません。それがNoSQLが心のシェアを獲得している理由です。

それがあなたが引用している例が言っていることだと思います。

RDBMSは、あなたが考えていないクエリ用です。必要なものを正確に確信したら、最も最適なソリューションを適用できます。

SQLまたはNOSQLのいずれかを使用すると、クエリを間違った方法で設計すると、パフォーマンスが恐ろしくなります。

Where句にタイムスタンプのチェックを追加して、その例を修正します。多くのデータがある場合、おそらく最新の10エントリが最後の最後のものであると仮定することができます。

デフォルトでは、IDでレコードしか見つけることができないため、必要なレコードを見つける必要があるため、さまざまなセカンダリをセットアップする機能を無視すると主張することで、NoSQLを悪く見せるために同じ例を簡単に考案することができます。 /重要なクエリのSQLパフォーマンスよりも良くなるカスタムインデックス。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top