Pull to refresh

Comments 17

Там в dbf байтик есть — кодовая страница. Мне кажется, что сменить его было немного проще.
Да, я знаю :-)
Но с dbf, к сожалению, стало слишком много мороки. И захотелось попробовать что-то новое.

Да и, собственно, статья не столько о том, как загрузить ФИАС, а о том, как манипулировать схемами, и грузить данные через SQLXMLBULKLOAD.
Я свою первую статью на хабре писал по загрузке dbf черех SqlBulkCopy, это как раз под фиас и делалось. Потом вроде даже универсальное приложение писал для любых dbf, если надо поищу.

UPD: нашел
Ага, я писал такое же, но с интерфейсом командной строки. В качестве драйвера использовал фокспрошный. Тоже через SqlBulkCopy.
Но не стал возиться с исправлением неправильной кодировки в файле.
Причешу, выложу. :-)
была подобная задача
пытались стандартными средствами MSSQL запихнуть, но отказалось жрать файлик больше 2Гб
тогда на шарпе написали загрузчик — примерно 5 часов жевал улицы (домов тогда не было еще)
а потом проще — дифференциальные обновления по 15 секунд в день
Ага :-)
Ограничение в 2Гб — это потому, что вы пытались использовать xpath/xquery, а сам xml запихнуть либо в blob поле, либо в переменную.
Это, видимо, какое то фундаментальное ограничение MSSQLSERVER. Уже 2019 версия на носу, а blob-ы как были 2 Гб, так и остаются.
С загрузкой то, как раз особых проблем нет. Загрузить данные можно или SQLXMLBULKLOAD, или с помощью SSIS, либо преобразовать данные на клиенте.
Проблемой становится, когда в результате выполнения запроса xml получается больше 2Гб.
Вот тут, как я понимаю, выхода кроме как понодно загнать в промежуточную таблицу и склеить на клиенте — нет.
(ну, или я не знаю как).
:-)

Вы упомянули SSIS… Не знаю… Я него ненавижу. Если надо работать с очень широкими таблицами то от количества кликов в GUI сходишь с ума.


Bulk insert (когда это возможно) быстрее, надежнее, и пишется быстрее.


Что касается XML, как то у меня была задача загрузки десятков миллионов записей из весьма плоского и простого XML. Как оказалось, тривиальная программа XML->CSV и последующий BULK INSERT быстрее всего

BIML может облегчить — создание SSIS пакетов
Спасибо большое, добрый человек. Как раз встала задача с ФИАС, написал приложение на C#, часть данных выгружает, но сходит с ума когда доходит дело до больших xml (AS_HOUSE). Запарился искать решения.
А. Понятно. Вы, видимо, пытались его или в DOMdocument, или опять же стандартными ридерами читать.
Я выходил из этого таким образом:
1. Открывал хмл как обычный текст-стрим.
2. Читал из потока от открывающего тега до закрывающего ветку, которая соответствует единичному набору данных, который я хотел сохранить в таблицу.
Потом было 2 версии программы:
Старая:
Формировал на клиенте набор датасетов, который соответствовал набору сущностей, хранящихся в ранее считанной ветке хмл, и вручную парсил данные в эти датасеты. Когда главный датасет (ну, в ветке хмля ж может храниться несколько сущностей) доростал до 1000 записей — делал его SqlBulkCopy на сервер.
Недостатки: Относительно трудно распараллеливается, для изменившихся хмлей нужно модифицировать код заливальщика, реляционные связи обеспечиваются трудно, разве что в качестве ключей синтезировать guidы в самом заливальщике.
Короче, для моих целей — слишком сложно, нудно и неинтересно.
Новая:
Формировал на клиенте — заливальщике короткий хмл, точнее — просто буферную строку из ~1000 веток, и скармливал хранимой процедурке, которая парсила ее уже на сервере, через xQuery, и раскладывала данные уже по реляционно-связанным таблицам уже согласно логике сервера, хоть через автоинкрементные поля, хоть через сиквенс, хоть через гуиды.
Достоинства: Заливальщик — простой как полено, универсальный и неизменный. Достаточно указать начальный нод ветки — и всё, может резать любой хмл. (Правда, пришлось немного подумать, если внутри ветки встречаются ноды, называющиеся одинаково с головным, т.с., но это фигня. Достаточно их считать :) ). Легко распараллеливается. Сформировал буфер — бросил хранимке асинхронно, если к тому моменту, как буфер сформировался еще раз — хранимка не отработала — запустил еще одну (лучше пул коннектов, конечно, использовать). Подстройка под другой вид хмлей производится вовне программы, простым способом, написанием отдельной хранимки, и не нужно перекомпилировать ничего. Заливка данных становится целиком дбашной задачей, не нужно объяснять программерам, как «живут» данные.
Недостатки: Это не bulk, а заливка с полным протоколированием, и сервер грузится, и с локами-дедлоками придется повозиться.
Кстати, советую, если будете так реализовывать — сразу предусмотреть рестарт хранимки, в случае если она валится из-за дедлока.
:-)
Три года назад грузил ФИАС в MySQL, при этом обнаружилось, что данные — «кривые», некоторые символы в выгрузке заменены на соотв. entities, и как итог — вылет за пределы описанной в XSD длины поля (см. www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1190752&msg=18947898). В нынешних выгрузках это починили? или, может, SQL Server сам справляется с обратной конвертацией?
А фиг его знает. По описанной выше процедуре грузится уже около года, ошибок вроде нет.
В статье, кстати, не описана валидация на соответствие xsd. Но, думаю, это не интересно в этом контексте.
uaggster
В статье, кстати, не описана валидация на соответствие xsd.

Так её и нет — MySQL не умеет работать со схемой. Грузились чисто данные. Но структуру составлял вручную по схеме — вот и не влезло.
Добрый день, спасибо что сказали про дефрагментацию.
Два дня мучился с разными решениями, но вот решил спросить инет и наткнулся на вашу статью.
Мое решение из dbf по 100к записей в temp.csv и bulk load
может кого заинтересует.
github.com/tnsr1/FiasLoad
Возникла похожая задача с новым ГАР, использовал похожее решение, но есть ещё одна задача, загружать из XML не все, элементы а только те у которых ISACTIVE = 1, посмотрел примеры/почитал документацию на docs.microsoft.com/ru-ru/sql/relational-databases/sqlxml/sqlxml-4-0-programming-concepts?view=sql-server-ver15

В примерах есть то что на первый взгляд нужно: Фильтрация значений при помощи sql:limit-field и sql:limit-value
Но как я понял из описания/примеров/практики эти аннотации используются при соединении с другими таблицами, и просто для фильтрации их использовать нельзя.

Есть еще вариант попробовать с xpath выражением
Указание логических операторов в запросах XPath (SQLXML 4.0)

Но никак не могу понять в какой момент файл с шаблоном xpath применяется, все примеры написаны так что вот файл шаблона, положите его рядом. Но при этом сам файл нигде не прописывается.
Есть еще упоминание про mapping-schema=«C:\MyDir\SampleSchema1.xml» но не пойму где это писать. Вроде как это в шаблоне нужно писать, но при этом изначально мы передаем не шаблон а схему, и как это работает не понимаю.
но есть ещё одна задача, загружать из XML не все, элементы а только те у которых ISACTIVE = 1

Если таковых записей — процентов 80, как минимум — не морочтесь. Грузите всё в промежуточную таблицу, а из нее — вставляйте с фильтрацией. Применение фильтра на клиенте, каким бы способом вы его не делали — снижает производительность радикально (ну, просто потому что ограничено ресурсами клиента, например).
Вот, если этих записей 1 из 100 — ну, тогда…
Sign up to leave a comment.

Articles