как получить данные тега заголовка xml в снежинке для большого xml при использовании STRIP_OUTER_ELEMENT = TRUE - PullRequest
0 голосов
/ 27 мая 2020

Я использую этот код для получения больших xml данных при постановке в снежинку, для чего мне нужно использовать STRIP_OUTER_ELEMENT = TRUE, возникает другая мудрая ошибка:

Ошибка синтаксического анализа XML: документ слишком большой, максимальный размер 16777216 байт

COPY INTO SAMPLE_DB.SAMPLE_SCH.T_TABLE (CATALOG_XML)
FROM @META_DB.CONFIG.STAGESNOWFLAKE/catalogmain.xml
FILE_FORMAT=(TYPE=XML STRIP_OUTER_ELEMENT = TRUE) 
ON_ERROR='CONTINUE';

НА ЭТОМ XML, очень большой

<catalog xmlns="http://www.demandware.com/xml/impex/catalog/2006-10-31" catalog-id="catalog1">
    <product product-id="prod1">
     ..
     ..
     ..
    </product>
</catalog>

И Я ПОЛУЧАЮ ЭТО РЕЗУЛЬТАТ КАК КАТАЛОГ_ XML: ( не получают данные тега каталога )

<product product-id="prod1">
 ..
 ..
 ..
</product>

Мне нужно получить идентификатор каталога из этого xml, есть ли есть способ получить это?

1 Ответ

1 голос
/ 27 мая 2020

При использовании STRIP_OUTER_ELEMENT = FALSE весь документ XML будет считан в одно значение. Независимо от того, приведен ли он как тип VARCHAR или VARIANT , в операторе COPY INTO или в прямом запросе файла ограничение размера 16 МиБ в Snowflake для эти типы данных нельзя обойти.

Вы можете попробовать разделить файл XML на части регулируемого размера, сохранив родительские теги и загрузив файлы меньшего размера, содержащие тот же объем данных.

Для Например, следующая программа javascript в Node.js может разбить файлы на фиксированное количество product элементов на файл, при сохранении внешнего элемента catalog в каждом файле . Это создает каталог с разбитыми файлами, которые можно загружать и запрашивать, не превышая лимит в 16 МиБ.

~> mkdir /tmp/xsplt /tmp/split_files && cd /tmp/xsplt
~> npm init && npm install xmlsplit

~> cat > splitter.js << EOF
var xs = require('xmlsplit')
var fs = require('fs')

// Split into 500 product element data per document
var xmlsplit = new xs(batchSize=500)
var inputStream = fs.createReadStream("/tmp/large-input.xml")

var counter = 1;
inputStream.pipe(xs).on('data', function(data) {
    var xmlDocument = data.toString()
    fs.writeFile(
        `/tmp/split_files/output-part-${counter}.xml`,
        xmlDocument,
        (err) => { if (err) { console.log(err) } })
    counter += 1
})
EOF

~> node splitter.js

# Original input line count
~> wc -l /tmp/large-input.xml
500002
# Lines per split file
~> wc -l /tmp/split_files/output-part-1.xml
502
# No. of smaller files
~> ls /tmp/split_files/ | wc -l 
1000

Другими альтернативами может быть попытка экспорта данных в CSV вместо XML или выполнить преобразование локального формата файла перед загрузкой данных в Snowflake.

Ps Для получения помощи при загрузке и запросе разделенных файлов обратитесь к самому раннему редакция этого ответа .

...