PostgreSQL:STARスキーマにデータを効率的にロードします
-
14-10-2019 - |
質問
PostgreSQL 9.0に次の構造があるテーブルを想像してみてください。
create table raw_fact_table (text varchar(1000));
単純化のために、私は1つのテキスト列のみに言及していますが、実際には1つのテキスト列があります。このテーブルには100億行があり、各列には多くの重複があります。テーブルは、fromを使用してフラットファイル(CSV)から作成されています。
パフォーマンスを向上させるために、次の星スキーマ構造に変換したい:
create table dimension_table (id int, text varchar(1000));
ファクトテーブルは、次のようなファクトテーブルに置き換えられます。
create table fact_table (dimension_table_id int);
私の現在の方法は、基本的に次のクエリを実行して、次のディメンションテーブルを作成することです。
Create table dimension_table (id int, text varchar(1000), primary key(id));
次に、私が使用するディメンションテーブルを入力するには:
insert into dimension_table (select null, text from raw_fact_table group by text);
その後、次のクエリを実行する必要があります。
select id into fact_table from dimension inner join raw_fact_table on (dimension.text = raw_fact_table.text);
すべての文字列を他のすべての文字列と数回比較することで、恐ろしいパフォーマンスを想像してください。
MySQLでは、コピー中にストアドプロシージャを実行できます。これにより、文字列のハッシュが作成される可能性があり、その後のすべての文字列比較は、長い生文字列の代わりにハッシュで行われます。これはPostgreSQLでは不可能に思えますが、その時私は何をしますか?
サンプルデータは、このようなものを含むCSVファイルです(整数とダブルの周りにも引用符も使用しています):
"lots and lots of text";"3";"1";"2.4";"lots of text";"blabla"
"sometext";"30";"10";"1.0";"lots of text";"blabla"
"somemoretext";"30";"10";"1.0";"lots of text";"fooooooo"
解決
質問に: - データを1つまたは2つのステップで変換することはネクタリーですか? - 変換中にテーブルを変更できますか?
よりシンプルなクエリを実行すると、パフォーマンスが向上する可能性があります(およびそれを行う際のサーバーの負荷)
1つのアプローチは次のとおりです。
- Dimension_Tableを生成します(正しく理解している場合、これについてパフォーマンスの問題はありません)(おそらく、追加の一時的なブールフィールドがあります...)
- 繰り返します:Dimension_Tableから以前に選択されていないエントリを選択し、それを含むraw_fact_tableからすべての行を選択し、fact_tableに挿入します。 Dimension_Tableレコードが完了したとおり、次に...これをストアドプロシージャとして書くことができ、バックグラウンドでデータを変換して最小限のリソースを食べることができます...
または別の(おそらくより良い):
- raw_fact_tableおよびone dimension_idのすべてのレコードとしてFact_Tableを作成します。 (dimension_textとdimension_id行を含む)
- Dimension_Tableを作成します
- fact_tableの挿入後トリガーを作成します。
- fact_tableでdimension_textを検索します
- 見つからない場合は、dimension_tableで新しいレコードを作成します
- このIDにdimension_idを更新します
- simleループで、すべてのレコードをraw_fact_tableからfact_tableに挿入します
他のヒント
すべての文字列を他のすべての文字列と数回比較することで、恐ろしいパフォーマンスを想像してください。
しばらくこれを行っていたとき、パフォーマンスを想像するのをやめ、測定を開始します。 「早期最適化はすべての悪の根源です。」
「10億」とはどういう意味ですか?私にとって、アメリカでは、1,000,000,000(または1E9)を意味します。それがあなたにも当てはまるなら、あなたはおそらく1〜7テラバイトのデータを見ています。
私の現在の方法は、基本的に次のクエリを実行して、次のディメンションテーブルを作成することです。
Create table dimension_table (id int, text varchar(1000), primary key(id));
一次キーに整数を使用するテーブルに100億列をどのように収まりますか?列の半分が複製であるとさえしましょう。あなたがそれをするとき、その算術はどのように機能しますか?
想像しないでください。最初に読んでください。次に、テストします。
読む PostgreSQLを使用したデータウェアハウジング. 。これらのプレゼンテーションスライドがあなたにいくつかのアイデアを与えると思われます。
また読んでください データベースの入力, 、および実装する提案を検討してください。
「分裂と征服」プロセスに続いて、100万列(1E6)の行でテストします。つまり、一度に100万をロードしようとしないでください。それを小さなチャンクに分割する手順を書きます。走る
EXPLAIN <sql statement>
少なくとも99%の重複行を推定していると言いました。大まかに言えば、デュペを取り除くには2つの方法があります
- データベース内では、必ずしも生産に使用するプラットフォームと同じではありません。
- データベースの外側、ファイルシステム内で、必ずしも生産に使用するファイルシステムと同じではありません。
あなたがまだロードしたテキストファイルを持っている場合、私は最初にデータベースの外部で試すことを検討します。このAWK One-Linerは、各ファイルから一意の行を出力します。それは比較的経済的であり、それはデータを1つだけパスするだけです。
awk '!arr[$0]++' file_with_dupes > file_without_dupes
実際に99%のデュープがある場合、このプロセスの終わりまでに、1〜7テラバイトを約50ギグに減らす必要があります。そして、それを行ったことで、それをデータウェアハウスにコピーする前に、各一意の行を数えてタブ固定されたファイルを作成することもできます。それは別の1ライナーです:
awk '{printf("%d\t%s\n", NR, $0);}' file_without_dupes > tab_delimited_file
Windowsの下でこれを行う必要がある場合、私は使用します Cygwin.
これをデータベースで行う必要がある場合は、本番データベースまたは生産サーバーの使用を避けようとします。しかし、多分私はあまりにも慎重です。いくつかのテラバイトを移動することは、高価なことです。
しかし、私はテストします
SELECT DISTINCT ...
グループを使用する前に。私はあなたのために大きなデータセットでいくつかのテストを行うことができるかもしれませんが、おそらく今週ではありません。 (私は通常、テラバイトサイズのファイルを使用していません。それはちょっと面白いです。待つことができれば。)
最後にいくつかの詳細を省略していますが、必ずしも問題があるとは思いません。すべての文字列が実際に他のすべての文字列と比較されることは証拠ではありません。結合を行うと、PostgreSQLは、ハッシュ結合など、よりスマートな結合アルゴリズムを非常によく選択できます。 (繰り返しますが、あなたの詳細はそれについてぼんやりとしています。)
-- add unique index
CREATE UNIQUE INDEX uidx ON dimension_table USING hash(text);
-- for non case-sensitive hash(upper(text))
ハッシュ(テキスト)を試してください。どちらがより速いかを確認するためにbtree(テキスト)
私はあなたの問題を解決するいくつかの方法を見るpostgresql md5(string)にmd5関数があります弦のmd5ハッシュを計算し、結果を16進数に戻します
Inserting Into Dimension_table(select null、md5(テキスト)、text by textによるraw_fact_tableグループからのテキスト)
md5フィールドをraw_fact_tableに追加するだけでなく、idをfact_tableにfact_tableに選択します。
提出されたMD5のインデックスも役立つ場合があります
または、データのロード中にその場でMD5を計算することもできます。たとえば、ETLツールAdvanced ETLプロセッサがあなたのためにそれを行うことができます。さらに、データを複数のテーブルに同時にロードできます。
たとえば、私たちのWebサイトで利用可能なオンラインチュートリアルがたくさんあります。