Pull to refresh

Comments 49

UFO just landed and posted this here
То, что ActiveRecord медленнее — это было очевидно. Удивило то, насколько он медленнее.
UFO just landed and posted this here
Добавил результаты в production окружении.
UFO just landed and posted this here
Мда, вставлять записи по одной при задаче импорта, при том что у Mysql есть все готовое для того чтобы делать пакетные вставки, может только махровый экспериментатор… :))

Ещё при этом завернуть каждый запрос в разные варианты оберток и устроить тестирование :)
Поддерживаю, работает намного быстрее. Xp0M0u, проверьте на том же кол-ве записей и приведите время для сравнения.
А вместо mysqlimport можно использовать команду LOAD DATA INFILE суть та же, только имейте ввиду, что у многих хостеров она не разрешена.
Добавил тест с bulk-insert.

Данные из CSV было необходимо определенным образом обработать перед заливкой в базу, поэтому напрямую брать из CSV и лить в MySQL — не получится.
Все равно для больших файлов лучше использовать mysqlimport или LOAD DATA, потому что у вас сначала файл читается в память, а потом передается в MySQL.
Само собой, csv-файл должен быть доступен для MySQL (один физ. сервер либо NFS и права доступа).
а залить в отдельную таблицу, над ней сделать действия и перенести в нужное место никак?
конечно что активрекорд медленнее.

но я не вижу у вас в sql.execute никаких валидаторов, сериализаторов, связей и других плюшек какие можно прописать в модель благодаря актив рекорду и не волноватся за правильность данных в цвс файле.
тут даже в другом проблема.
изначально автор насоздовал over 9000 объектов и по отдельности их сохранял — это тактика северного пушного зверя
к концу автор исправился, правильно создать массив хэшей, сделать из него sql и ActiveRecord::Base.connection.execute(sql)
кстати валидацию можно выключить
ORM должны поддерживать массовые операции.
Импортировать CSV файл из 5к строк за 30 секунд — нормально. Главное грамотно GUI сделать.

Имхо, единственный случай, где надо это оптимизировать — постоянные частые процедуры импорта. Когда 30 секунд раз в час (к примеру) уже дают о себе знать. Но и даже тут я бы лучше подумал как уменьшить входные данные, чем оптимизировать код.
5к строк — только в тестовом коде. В реале строк больше 100к и ждать приходилось дольше 5 минут.
Уточню — в CSV файле строк около 3000, но на основе этих данных, по разным табличкам разносится более 100к записей.
Ой-ой-ой. Это нормально?)
100к строк в файле импорта? Простите, а что импортить надо? Может, проблемы не в импорте, а все же во входных данных?
5k строк за 30 секунд это совсем ненормально на современном оборудовании, даже при красивом GUI.
У меня дампы на 150-200Мб в мускул грузятся за 10-15 секунд, на стареньком P4 именно за счет bulk-insert. Тот же самый дамп, но в старой нотации — один инсерт-одна запись будет грузиться минимум пару часов.
О, я уже успел у автора про «булки» спросить напрасно.
На самом деле вопрос не в нормальности. Вопрос в том, стоит ли тратить время и ухудшать читаемость программы, увеличивать кол-во рисков и т.п. ради оптимизации процесса, который совсем не факт, что надо оптимизировать.
Вы клиенту текст программы даете почитать? Читаемость программы это следствие корпоративных стандартов оформления кода и профессионализма разработчика, а не использования прослоек.

Увеличение количества рисков это прямое следствие от усложнения программы, в данном случае шансов нарваться на непредвиденную ситуацию с прослойкой больше, чем с нативным функционалом БД с которой работаете. Да в принципе этот топик и показывает такую непредвиденную ситуацию.

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

ЗЫ. Мне это напоминает 1С бухгалтерию, когда 1Сники в захлеб рассказывают какая у них там большая база, целых 4Gb, и как быстро у них там проводка генерится — аж целых 5 секунд. И впадают в ступор, когда моя маленькая база в 120+Gb, выдает за теже 5 секунд аналитику по десятку миллионов строк.
Введением абстракций читаемость не повысить? Фреймворки не упрощают разработку?

Корпоративные стандарты тут вообще ни причем. Если разработчики пишут быдлокод, никакие стандарты не помогут.

Увеличением кол-ва рисков будет использовать SQL вместо хорошего ORM. Рефакторинг (или любые изменения функциональностей) кучи SQL запросов — ад. Опыт уже имеется.

Про 1С… Вопрос: насколько часто надо делать эту самую статистику? Раз в час? Раз в минуту? Или все же раз в неделю максимум? Насколько конечным пользователям мешает выполнение алгоритма в 10 раз дольше? Логично предположить, что их пользователи не особо жалуются, раз ситуация до сих пор такая. Так зачем 1С тратить лишние ресурсы на то, что и так работает?

Так вот, я пишу программы так, чтобы их могли легко прочесть и легко менять. ORM фреймворки значительно упрощают это. Любую же оптимизацию я начинаю делать только после очень хорошего исследования ее надобности.

Когда на половине проекта заказчик попросит изменения, которые поменяют структуру половины таблиц и ваша IDE не сделает автоматический рефакторинг кастомного SQL кода, вот тогда и начнется настоящий геморрой.

Оптимальным же в этой задаче, имхо, будет:
— Понять насколько *действительно* актуален прирост производительности. Делается ли он в угоду пользователям или только для удовлетворения собственных амбиций.
— Подумать как можно оптимизировать входные данные (актуально для данной задачи)
— Сделать изменения в ORM
— …

Понимаю, я — никто и мысли свои выражать не умею. Почитайте «Совершенный код» Макконнелла, раздел про оптимизацию программ — там об этом написано лучше.

ЗЫ: Я сам очень люблю удовлетворять свои амбиции и тратить ресурсы не оптимально. Но очень часто понимание того, что это имеет мало общего с заработком денег, отрезвляет.
Я уже отмечал в предыдущем посте, абстракции и фреймворки это палка о двух концах, с одной стороны мы ускоряем (не упрощаем, а именно ускоряем) выход рабочего кода, но при этом ловим все баги фреймворка и «псевдогибкость» абстракций пытающихся описать неописуемое.
В моей работе время от времени возникают ситуации, когда непредвиденное поведение программы связано со сторонней библиотекой или фреймворком. Так что цена «удобства» разработки — вычитка чужого кода.

А быдлокод можно написать и с фреймворками, и с абстракциями, они эту проблему ни в коем разе не решают.

Про 1С. Пользователи то как раз и жалуются, я постоянно вижу как бухгалтерия сидит ночами и выходными, только чтобы успеть в отведенные временные рамки по закрытию отчетного периода, и немалую часть времени занимает ожидание чего же там «додумает» 1С.

Насчет Макконела — рассуждения в книге здравые, и я не собираюсь их оспаривать. Оптимизация ради оптимизации — всегда зло. Другое дело, что тот же Макконел замечает, что «написание эффективного кода — это уже признак серьезного программиста».

Но мы несколько отвлеклись, данный топик как раз показывает случай когда оптимизация нужна по условиям задачи и не решается красивой высокоуровневой абстракцией.
По поводу работы с БД кстати рекомендую Тома Кайта почитать, Oracle Experts, в русском переводе «Оракл для профессионалов». Книга конечно прежде всего про оракл, но общие вводные главы содержат много примеров как надо и как ненадо работать с БД, чтобы она не стала узким местом.
Спасибо за книгу, обязательно почитаю.
А там у вас в рубях и mysql нет BULK операций что-ли?
И без TestObject.new(item). Что-то типа:

require 'ar-extensions/adapters/mysql'
require 'ar-extensions/import/mysql'

TestObject.import [:field1, :field2, :field3, :field4, :field5], array_of_values, :validate => false
можно ещё ускорить, сделав длинные инсерты, вставляющие за раз несколько записей, а так же можно использовать prepared statement
но нафег? целостность данных, валидация в подобных операциях гораздо важнее скорости, модель это больше нежели просто вставка.
У приличных RDBMS и при BULK-операциях есть все необходимое для обеспечения целостности данных и отлова исключений. Думаю, что и в MySQL не дураки далеко сидят.
имелось ввиду целостность модели, которая является не только записью в одной таблице, но и вероятно связанные записи в других таблицах, связанные файлы, специализированные сетеры. конечно, есть тригеры, но в коде гораздо больше возможностей.
Я это прекрасно понимаю, поэтому я и написал «в тех участках кода, где не нужны его широкие возможности и важно быстродействие». Часто требуется только экранировать спец символы перед инсертом.
prepared не только экранирует, но и говорит базе, жди ещё запросов, соответственно последующие запросы будут выполняться шустрее, в зависимости от дб.
:( эх, проклятые пять минут.
в инсерте в одном запросе можно вставлять много строк (insert table (columns) values (values), (values),(values),(values),(values),...) так даже быстрее, чем в транзакции…
(я просто счас лог аналайзер и сервер статистики пишу — ulog и squid логи парсю — там этих инсертов — очень много, пришлось изучать...)
А еще можно сделать insert from outfile (если в нем только нужные данные) — с csv, подходящего формата прокатывает.
в смысле сделать временную таблицу, загнать в нее
LOAD DATA INFILE 'file_name.txt' INTO TABLE tbl_name
и потом INSERT… SELECT
Ну вот, еще один человек узнал, что ORM медленнее, чем запись в базу через SQL.
Слушайте, а неужели все ORM'ы могут только обрабатывать по одной записи за раз? Неужели они не позволяют работать с набором записей одним запросом? Всякие bulk-delete не считаются, тк они не вызывают onDelete и не удаляют связанные записи.

Нафиг тогда вам сдался такой такой ОРМ?
Да ну? Не эксперт по RОR'у, но почти уверен что его ORM не настолько уж убог.
Ну ORM системы бывают разные, некоторые поумнее, некоторые покондовее. Но суть в том, что это не волшебная таблетка от всего. Если вам не хочется, чтобы было много запросов — вы просто реализуте часть логики работы с бд в вашей модели, используя для этого наследование и другие возможности языка, для этого в том же ActiveRecord есть все необходимое для регулирования уровня абстракции взаимодействия с бд. На этапе проектирования и первичной реализации это бывает не так существенно, а потом все эти моменты легко совершенствуются. Как-то так.
Не плохо былобы еще DataMapper пробенчмаркерить.
в чем вы хотите убедить? в том, что надо писать голыми SQL? тогда вообще выкиньте этот AR, используйте Ruby-DBI.
«я ни в коем случае не призываю отказаться от его использования, но в тех участках кода, где не нужны его широкие возможности и важно быстродействие, лучше использовать обычные SQL-запросы.»
Вы дочитали пост до конца?
Тут все говорят о mysql, складывается такое впечатление, что mysql это единственный сервер для баз данных.
Самому писать sql-запросы нельзя, проблемы возникнут при переходе на другой бд-сервер (mysql > postgresql …).
Ваше приложение становится зависимым от конкретного типа бд, и лучше этого избегать.
Sign up to leave a comment.

Articles

Change theme settings