Closed sakaik closed 1 month ago
SELECT * で見るとそれっぽくデータが見えていたのですが、件数をが本来よりも多く認識されていることがわかりました。もとのpostgresテーブル(Arrow化する元のデータ)は1000万件です。
db=# SELECT COUNT(*) FROM arrowtest1;
count
----------
11545600
id列は連番なので、この重複を確認することで状況がわかるだろうと見てみたところ・・・
db=# SELECT no,COUNT(*) FROM arrowtest1 GROUP BY no HAVING COUNT(*)>1;
:
7099069 | 4
6081399 | 4
4883584 | 4
6350052 | 4
6365021 | 4
5623091 | 4
(2886400 rows)
4件ずつ存在するという結果が得られました(おかしい)。この際に、countが1件になるものは存在しません。
db=# SELECT no,COUNT(*) FROM arrowtest1 GROUP BY no HAVING COUNT(*)=1;
no | count
----+-------
(0 rows)
2886400 * 4 = 11545600 なので、ここの計算は整合しているようです。
また、このとき、以下のNOTICEが発生していました。
NOTICE: arrow scan on 'arrowtest1' moved into 2th loop for inner-buffer partitions (pid: 200500)
NOTICE: arrow scan on 'arrowtest1' moved into 4th loop for inner-buffer partitions (pid: 200500)
NOTICE: arrow scan on 'arrowtest1' moved into 3th loop for inner-buffer partitions (pid: 202124)
"dir"の問題として当初報告しましたが、そもそもひとつのArrowファイルが適切に生成されていない可能性(または正しく読み込めていない可能性)が高くなってきたので、その方面で追試を行いました。
COUNT()での件数が不正な値を返すようになるのは、今回の例のデータ(6 + int + 16 + 16 + 16 + 8 + 8 byteのレコード)だと、188.5万件~188.7万件の間に不正となる閾値があることが分かりました。(188.5万件以下のデータ件数(生成した件数)ではCOUNT()は正しい値を返す)。
また、16バイトではなく14バイトとしてデータ生成刺せた場合(6 + int + 14 + 14 + 14 + 8 + 8 byteのレコード)は、この閾値は 308.5万件と308.7万件の間へと変化します。
一定のデータサイズを超えた場合に pg2arrowが正常に動作しない可能性のように見えます。
要らぬ情報かもしれませんが、追加情報を取得したので。 14バイト文字列にした3つの列を12バイトにした場合、つまり(6 + int + 12 + 12 + 12 + 8 + 8 byteのレコード)では、 331.3万でOK 331.5万で件数相違となりました。
本issue、"dir"の問題 → "file"単体でもデータが変だった という点から 「pg2arrowの問題」として見ていましたが、どうも arrow_fdwの問題ではないかとの可能性が出てきたので、追加情報です。
(1) 単体でも正しく読めないarrowファイル data00410.arrow
を、arrow2csvで変換、2列目(連番が入っている)だけを抽出
$ arrow2csv data00410.arrow | awk '(FS=","){print $2}' > z
(2) 出力された行数を確認 これは期待する件数と一致しています。
$ wc z
33554432 33554431 290878777 z
(3) idがユニークとなる件数(種類数) 上の(2)と一致し、arrowファイル自体にはidの重複がないことがわかります(これを import foreign schemaするとidの重複があるように見えます)。
$ cat z | sort | uniq | wc
33554432 33554431 290878777
故に、「pg2arrowは正常にarrowファイルを生成しているが、arrow_fdwが正しく読めていない」可能性として改めて報告いたします。
複数のArrowファイルを比較する際に、FixedSizeBinary型への考慮が抜けていることが原因と思われます。
また、この時表示されるエラーメッセージ(default:の部分)は、a->node.tagName
よりも a->type.node.tagName
のほうがわかりやすいのではないでしょうか。
diff --git a/src/arrow_nodes.c b/src/arrow_nodes.c
index 5bee69e8..d2daf329 100644
--- a/src/arrow_nodes.c
+++ b/src/arrow_nodes.c
@@ -1033,6 +1033,7 @@ __arrowFieldTypeIsEqual(ArrowField *a, ArrowField *b, int depth)
}
break;
case ArrowNodeTag__Utf8:
+ case ArrowNodeTag__FixedSizeBinary:
case ArrowNodeTag__Binary:
case ArrowNodeTag__Bool:
break;
@@ -1094,7 +1095,7 @@ __arrowFieldTypeIsEqual(ArrowField *a, ArrowField *b, int depth)
default:
Elog("'%s' of arrow type is not supported",
- a->node.tagName);
+ a->type.node.tagName);
}
return true;
}
FixedSizeBinaryの互換性チェックはbyteWidthの比較も必要ですので、
9d2df1d33422aa8076e01f81f91659badca86b61
でその辺も交えて修正してみました。
ご確認いただけますでしょうか?
9d2df1
にて、当該Arrow filesが正常にIMPORTでき、テーブルとして参照できるようになったことを確認しました。
対応ありがとうございました。
db=# IMPORT FOREIGN SCHEMA mytable
db-# FROM SERVER arrow_fdw INTO public
db-# OPTIONS(dir '/opt/nvme/mydata/arrow_files/', suffix 'arrow');
IMPORT FOREIGN SCHEMA
Time: 22589.879 ms (00:22.590)
db=# SELECT COUNT(*) FROM mytable;
count
-------------
36943429632
(1 row)
db=# SELECT pgstrom.githash();
githash
------------------------------------------
9d2df1d33422aa8076e01f81f91659badca86b61
概要
IMPORT FOREIGN SCHEMA で、オプションとして "dir" を指定した際にエラーになります。 実行例:
詳細状況
Arrowファイル
このフォルダには3つのarrowファイルがあります。
各Arrowファイルは "file" オプションで読み込める
再現データ作成方法
データ作成用スクリプトの用意
https://github.com/heterodb/pg-strom/issues/824 に記載したpythonスクリプトを用意する。
データ生成~登録~Arrow化のためのシェルスクリプトファイルを用意
以下のシェルスクリプトファイルを用意する。DB名やDBユーザ名、出力先フォルダは適切に書き換える。
シェルスクリプトを実行
1,2,3のパラメタを与えて、シェルスクリプトを3回実行する(3つのArrowファイルが作成される)。
Arrowファイルが作成されたら、上記 IMPORT FOREIGN SCHEMA の with Option で動作を確認できる。