Có thể có hàng nghìn cách để nhập tệp XML vào PostgreSQL, nhưng đây là một giải pháp thay thế mà tôi thấy khá dễ thực hiện và đã được thử nghiệm với các tài liệu xml lớn (120GB +)
Tùy thuộc vào kích thước tệp XML của bạn, hãy xem xét việc chia nhỏ nó. Một công cụ tuyệt vời để làm như vậy là xml_split
. Lệnh này chia nhỏ file.xml
trong các tệp nhỏ hơn với tối đa 100MB:
xml_split -n 5 -l 1 -s 100MB file.xml
Khi bạn đã phân chia tệp của mình ở kích thước hợp lý, bạn có thể bắt đầu nhập chúng mà không gặp rủi ro hết bộ nhớ.
Hãy xem xét cấu trúc tệp XML sau ...
<?xml version="1.0"?>
<t>
<foo>
<id j="a">1</id>
<val>bar1</val>
</foo>
<foo>
<id j="b">8</id>
<val>bar1</val>
</foo>
<foo>
<id j="c">5</id>
<val>bar1</val>
</foo>
<foo>
<id j="b">2</id>
</foo>
</t>
... và bảng đích sau đây, nơi chúng tôi sẽ chèn các bản ghi XML.
CREATE TABLE t (id TEXT, entry XML);
Đoạn mã dưới đây nhập các tệp XML vào một đã mở khóa
table và unnest
chúng vào bảng t
sử dụng CTE
(hay còn gọi là mệnh đề VỚI) bởi nút <foo>
. Lệnh perl -pe 's/\n/\\n/g'
thay thế các ký tự dòng mới bằng \\n
để bạn không nhận được Premature end of data
ngoại lệ:
#!/bin/bash
psql testdb -c "CREATE UNLOGGED TABLE tmp (entry xml);"
for f in /path/to/your/files/;do
cat $f | perl -pe 's/\n/\\n/g' |psql testdb -c "COPY tmp FROM STDIN;"
psql testdb -c "
WITH j AS (
SELECT UNNEST(XPATH('//t/foo',entry)) AS entry FROM tmp
)
INSERT INTO t
SELECT XPATH('//foo/id/text()',j.entry),j.entry FROM j;
TRUNCATE TABLE tmp;"
done
psql testdb -c "DROP TABLE tmp;"
Và đây là dữ liệu của bạn:
testdb=# SELECT * FROM t;
id | entry
-----+--------------------------
{1} | <foo> +
| <id j="a">1</id>+
| <val>bar1</val> +
| </foo>
{8} | <foo> +
| <id j="b">8</id>+
| <val>bar1</val> +
| </foo>
{5} | <foo> +
| <id j="c">5</id>+
| <val>bar1</val> +
| </foo>
{2} | <foo> +
| <id j="b">2</id>+
| </foo>
(4 Zeilen)