Nick Sergeev
.NET
ORM vs Plain SQL
14.09.2012
|
nick sergeev |
gotdotnet не работает, попробую написать здесь.
Недавно в силу профессиональной занятости пришлось проводить перфоманс ревью одного проекта, который перестал адекватно работать при планируемой нагрузке. В сервис-деске запросили Visual Studio Ultimate для лоад тестов, подняли кластер из 3 машин — тест-контроллер, БД и сервер приложения и приступили к тестированию.
Ситуация следующая, при наращении нагрузки до 5 пользователей, SQL сервер выходит в плато на 100% CPU загрузки. При этом должен заметить, что сервер нам удалось получить очень мощный: 16 GB RAM, 8 Cores, RAID 0 x 4 HDD, ну в общем, кто знает тот поймет. Такая загрузка при таком количестве пользователей выглядит, мягко говоря, ненормально. Переписали на Plain SQL, запрос конечно получился не элементарный, заджойнили больше 8 таблиц. Поддержка всего этого дела сулит неприятностями. Запускаем тесты — нагрузка сервера БД держится на уровне 25%, а количество операций возросло в несколько раз. ОК, пишем отчет, получаем деньги.
Хотел расписать долго, но суть то в итоге коротка, пока архитекторы не понимают, что БД это самостоятельный организм, который требует инвестиций собственных мозгов — такие как мы будем получать овертаймы, сэйвшиты и прочие $$.
Недавно в силу профессиональной занятости пришлось проводить перфоманс ревью одного проекта, который перестал адекватно работать при планируемой нагрузке. В сервис-деске запросили Visual Studio Ultimate для лоад тестов, подняли кластер из 3 машин — тест-контроллер, БД и сервер приложения и приступили к тестированию.
Ситуация следующая, при наращении нагрузки до 5 пользователей, SQL сервер выходит в плато на 100% CPU загрузки. При этом должен заметить, что сервер нам удалось получить очень мощный: 16 GB RAM, 8 Cores, RAID 0 x 4 HDD, ну в общем, кто знает тот поймет. Такая загрузка при таком количестве пользователей выглядит, мягко говоря, ненормально. Переписали на Plain SQL, запрос конечно получился не элементарный, заджойнили больше 8 таблиц. Поддержка всего этого дела сулит неприятностями. Запускаем тесты — нагрузка сервера БД держится на уровне 25%, а количество операций возросло в несколько раз. ОК, пишем отчет, получаем деньги.
Хотел расписать долго, но суть то в итоге коротка, пока архитекторы не понимают, что БД это самостоятельный организм, который требует инвестиций собственных мозгов — такие как мы будем получать овертаймы, сэйвшиты и прочие $$.
14.09.2012 20 комментариев |
H>БД это самостоятельный организм, который требует...
самостоятельного онанизма.
Всё просто: если ORM позволяет что-то сделать быстрее и проще прямого SQL'я — его имеет смысл использовать, ибо по итогу всё равно придётся проводить нагрузочное тестирование/анализировать репорты сервера БД, и даже более того — оптимизировать систему целиком.
H>Запускаем тесты — нагрузка сервера БД держится на уровне 25%, а количество операций возросло в несколько раз. ОК, пишем отчет, получаем деньги.
Во-первых, ORM нужно уметь готовить, как это ни банально звучит. Во-вторых, нужно использовать правильную ORM, желательно такую, которая не даст себя приготовить неправильно.
Совсем недавно в результате переписывания прямого SQL на ORM на этом сайте, вот эта страница стала работать на пару порядков быстрее и у неё добавилось фукнциональности. Раньше мы тут уходили в даун и получали time-out exception.
IT>Здравствуйте, huligun, Вы писали:
IT>Совсем недавно в результате переписывания прямого SQL на ORM на этом сайте, вот эта страница стала работать на пару порядков быстрее и у неё добавилось фукнциональности. Раньше мы тут уходили в даун и получали time-out exception.
Это говорит лишь о том, что вы плохо знаете SQL. ORM соотносится с прямым SQL примерно так, как автоматический языковый переводчик с реальным человеком переводчиком. То есть — быстро, некачественно, но, порой, приемлимо. Ибо быстро, и, главное, не требует знания языка.
S>Это говорит лишь о том, что вы плохо знаете SQL. ORM соотносится с прямым SQL примерно так, как автоматический языковый переводчик с реальным человеком переводчиком. То есть — быстро, некачественно, но, порой, приемлимо. Ибо быстро, и, главное, не требует знания языка.
Я же говорю, нужно использовать правильные ORM, которые соотносятся с прямым SQL на 100%, не пытаются втихаря шаманить и додумывать за разработчика, а выполняют в точности то, что им сказано и делают это по возможности эффективно.
Что касается нашего случая, то, конечно же, победил не ORM, а полное переписывание старого кода. Старый SQL пытались оптимизировать, но не очень успешно. ORM всего лишь позволил переписать код быстро, поиграться с разными вариантами запросов, т.е. сделать то, что на прямом SQL заняло бы на порядок больше времени.
IT>Здравствуйте, Steamus, Вы писали:
IT>Я же говорю, нужно использовать правильные ORM, которые соотносятся с прямым SQL на 100%, не пытаются втихаря шаманить и додумывать за разработчика, а выполняют в точности то, что им сказано и делают это по возможности эффективно.
Это и будет прямой SQL плюс небольшой кусок кода, создающий объект и инициализирующий его поля из результата SQL запроса. Возможно делающий это несколько раз для создания массива объектов.
S>Здравствуйте, IT, Вы писали:
IT>>Здравствуйте, huligun, Вы писали:
IT>>Совсем недавно в результате переписывания прямого SQL на ORM на этом сайте, вот эта страница стала работать на пару порядков быстрее и у неё добавилось фукнциональности. Раньше мы тут уходили в даун и получали time-out exception.
S>Это говорит лишь о том, что вы плохо знаете SQL. ORM соотносится с прямым SQL примерно так, как автоматический языковый переводчик с реальным человеком переводчиком. То есть — быстро, некачественно, но, порой, приемлимо. Ибо быстро, и, главное, не требует знания языка.
Владимир Кочетков поставил кокетливый смайлик на моё сообщение, что видимо должно означать снисходительный намёк на то, что человек отлично владеет SQL и проблема как бы глубже моего уровня её понимания. Я верю. Ну, тогда, парни, и пишите конкретнее. Ибо сообщение вида — программа генерирует более умный SQL, чем квалифицированный разработчик... оно ведь других вариантов не оставляет.
S>Владимир Кочетков поставил кокетливый смайлик на моё сообщение, что видимо должно означать снисходительный намёк на то, что человек отлично владеет SQL и проблема как бы глубже моего уровня её понимания. Я верю. Ну, тогда, парни, и пишите конкретнее. Ибо сообщение вида — программа генерирует более умный SQL, чем квалифицированный разработчик... оно ведь других вариантов не оставляет.
А кто-то где-то говорил, что "программа генерирует более умный SQL, чем квалифицированный разработчик"?
IT>А кто-то где-то говорил, что "программа генерирует более умный SQL, чем квалифицированный разработчик"?
Нда, верно. По сути вы сказали, что редизайн старого кода увеличил производительность и что А ORM, по любому, нужно "уметь готовить".
S>Владимир Кочетков поставил кокетливый смайлик на моё сообщение
Мда, от дальнейшего общения в данной теме я, пожалуй, воздержусь. А то вдруг еще решишь, что я заигрывать начал...
H>Отвечу просто, мой кумир stackoverflow, а они давно перешли на Dapper
Dapper — это другая крайность. Это простенький маппер, в которой абсолютно всё без разбора принесено в жертву производительности. От него помощи в работе с SQL — чуть. А после появления в C# анонимных типов и инициализаторов чуть больше, чем ничего. Его эффект проявляется только при очень большом количестве очень маленьких запросов к БД, где маппинг действительно играет существенную роль. Большинство ORM, особенно тяжёлых, ему в этом вопросе сливают как стиральная машина после стирки.
Но то о чём говорит ТС совсем другая история. 8 джоинов — это не тривиальныый запрос. На его фоне затраты на маппинг не видны даже в микроскоп, если, конечно, не используется какой-нибудь абсолютный тормоз, типа сабсоника или NH. Для таких задач у нас на первый план выходят системы, которые облегчают прежде всего работу с SQL, его простую генерацию и по возможности валидацию во время компиляции. И как раз вот тут Dapper сосёт вместе с плоским SQL как трофейный пылесос. Я уже приводил тут свой пример. С плоским SQL просто никто не хотел связываться, а на Linq эту проблему решили в лёт. Могу показать код, если надо, чтобы оценить простоту решения и сложность генерируемого SQL.
IT>Могу показать код, если надо, чтобы оценить простоту решения и сложность генерируемого SQL.
да, любопытно
тут как бы еще проблема в том, что мы не видим запрос, который генерил ORM до переписывания на plain-SQL.
если там был select 1+n, то это не проблема ORM как таковая.
Но объем кода сгенерированный ОРМ получился в несколько раз больше ручного кода, что также является сложностью для сервера БД,
так как ему все это нужно как минимум парсить.
А>Нет, там действительно просто один тяжелый запрос с джоинами и подзапросами.
А>Но объем кода сгенерированный ОРМ получился в несколько раз больше ручного кода, что также является сложностью для сервера БД,
А>так как ему все это нужно как минимум парсить.
plain-sql ему тоже нужно парсить.
неужто ORM сгенерировал на столько кривой код?
было бы интересно сравнить. и знать что за ORM такой )
E>неужто ORM сгенерировал на столько кривой код?
Скорее всего там был сгенерирован не один запрос.
Это C# код с моими комментариями:
Здесь у нас 4 версии запрос в зависимости от параметров. Сначала берётся Count, т.е. 4 возможных варианта запроса, затем по необходимости строится пейджинг и выполняется запрос. Итого 12 вариантов запроса
Далее 3 запроса (из 12 возможных) на SQL:
Получение Count:
Выборка первых записей:
Пейджинг:
Эти три запроса принципиально разные, остальные вариации на тему.
Теперь внимательно смотрим, сравниваем количество кода, представляем какие усилия потребовались бы для ручного выпиливания 12-ти вариантов прямого SQL, ищем что сгенерировано не так.
IT>Это C# код с моими комментариями:
Ты всегда переменные называешь t, a, f, m, q1?
IT>>Это C# код с моими комментариями:
А>Ты всегда переменные называешь t, a, f, m, q1?
Длинные имена локальных переменных — это мусор в коде. Впрочем, это всё вкусовщина.