Как стать автором
Обновить

Комментарии 15

Вот мне интересно, как думают люди которые пишут про "низкоуровневый SQL".
В реальности SQL, как правило сильно выше уровнем чем тот код, который его использует. SQL реально абстрагирует клиентов от того как хранилище в конкретной БД реализовано. А вот клиентский код, как правило, "прибит гвоздями" к представлению данных в памяти процесса.

LINQ, пожалуй, первая попытка подтянуть средства современных языков до уровня SQL. Остальные же ОРМ предлагают нам вместо относительно универсального SQL, привязанное к конкретному языку кривое подмножество этого самого SQL. Ну и кучу разных веселых проблем в качестве бонуса :(

Код SQL выше уровнем, чем клиентский код его использующий? Это как? Поясните.

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

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

Ну так это к SQL коду непосредственно отношения не имеет. Вы здесь описываете частный случай денормализации данных, т.е. создать рядом мапу(ы) из нормализованных полей данных для ускорения поиска по частому конкретному запросу. Это скорее к теории отношений БД: как их правильно составлять и проектировать размещение данных. Никто ведь не заставляет клиентский код прибивать гвоздями к этим мапам: их можно агрегировать в соответствующие вьюхи и использовать через ORM как обычные таблицы. Вот SQL код во вьюхах и пусть оптимизирует сама БД, она и статистику соберет по запросам. И у вас выходит, что в клиентском коде зашито знание как эти данные хранятся в БД. А клиентскому коду по-хорошему знать об этих приседаниях не надо.

Другое дело, что от этого легко уйти на словах, а на практике все не так радужно. В наших проектах тоже активно используется EF и нет-нет да и прорываются запросы на голом SQL (кастомные отчеты или хитрые запросы, будь они не ладны). Те же хранимки хочешь не хочешь содержат в себе часть бизнес-логики т.е. знают как собирать данные для ответа клиенту.

Каждый раз приходя на очередной проект и видя развесистый EF спрашиваю местных: в чем сила брат? в чем преимущество использования здесь ORM'а? И обычно первым же ответом идет чтобы легче переехать на другую СУБД "если что". Причем это самое "если что" не уточняется и не случалось чуть ли не десятилетиями. Для меня же это в первую очередь продуманная инфраструктура, удобный генератор миграций, валидация моделей классов, встроенное кеширование и прочие плюшки оптимизаций запросов. Поэтому при всех недостатках ORM'а все же выступлю за его использование. Однако учитывая текущую ситуацию все же раз в пару десятков лет это самое "если что" стреляет. Вот и у нас на горизонте замаячила задача переезда с MS SQL на что-то опенсорсное.

Не совсем так. Я имел ввиду то, как клиент работает с данными у себя в памяти. Клиенту приходится значительно больше внимания уделять тому как данные у него в памяти размещены, какие ему понадобятся вспомогательные стурктуры и т.д. А уж переключить алгоритм выборки в зависимости от условий запроса он никак не может - это всё перекладывается на разработчика, а это, чаще всего, слишком сложно для реализации в конкретном случае.

Именно с этой точки зрения SQL более высокоуровневый - он скрывает сильно больше деталей реализации и избавляет клиентов от большого кол-ва рутины.

На счет встроенной миграции - соглашусь. В мире БД с этим есть проблемы.
На счет кэширования - скорее нет. Пусть лучше будет больше кэша в самой БД чем entity level кэш в ОРМ со всем прилагаемыми проблемами. Просто потому, что проблем с инвалидацией кэшэй в БД я не припоминаю, а вот в ОРМ - вполне себе.

На счет валидации - в целом, фича хорошая - статической типизацией нужно пользоваться. Только, ИМХО, реализовывать это нужно было бы немного по-другому. Но тут стреляет другая проблема мэйнстримовых ЯП, мало кто дает выполнить какой-то свой код на этапе "компиляции" чтобы проверить, что все поля запроса на месте и типы данных у них совместимы с кодом.

А почему выбрали MySQL, после MSSQL, а не PostgreSQL? Там и проблем с типами не было бы, и аналог rowversion есть https://www.postgresql.org/docs/current/ddl-system-columns.html . По мне так MySQL выглядит больше как даунгрейд СУБД в этом плане, если конечно вы осознано выбирали MySQL под очень узкий тип задач.

Mysql неосознанно выбран более десятка лет назад и используется почти во всех наших проектах, так что теперь мы слишком хорошо знаем, как его готовить, чтобы имело смысл переходить на постгрес.

Почему на рободьяволе реклама пиццы?

Как бы этот логотип более узнаваем, чем лого dodo engineering.. и по цветам лучше подходит.

Хочется заметить, что в 2011 году мускуль и постгря были совершенно другими базами, и никто не мог предсказать траекторию их развития. У постгрес так вообще тогда были серьёзные проблемы с репликацией, что объективно отпугивало от её использования. А картинка классная, спасибо)

Нужно было взять для перезаливки данных расширение linq2db.EntityFrameworkCore - там легко делается пайплайн из исходной таблицы и вставка в таргет. Вставка присходит быстро и не нужно дополнительных телодвижений.

Приблизительный пример как это могло быть:

using var sourceContext = new MyDbContext(sourceOptions);
using var targetContext = new MyDbContext(targetOptions);

targetContext.BulkCopy(sourceContext.SomeTable.AsNoTracking().AsEnumerable());
targetContext.BulkCopy(sourceContext.SomeOtherTable.AsNoTracking().AsEnumerable());
... // и тд.

Можно сделать обобщенные фукции которые могут заливать инкрементарно или перезапускать заливку если данные в таблице есть, а количество не совпадает.

Также ничего не мешает сериализировать классы в файлы и загружать их если источник недоступен.

На заметку - есть ещё такая удобная визуальная тулза для переноса данных из одной бд в другую - Pentaho Data Integration (вроде бы она же называется Kettle, а сам исполняемый файл Spoon). Вот ссылка на community edition - https://sourceforge.net/projects/pentaho/files/Data Integration/7.1/

В своё время очень помогла при миграции с MS SQL и с Oracle на Postgres. Впрочем она написана на Java и поддерживает любые JDBC драйвера.

Я перевозил один проект с on-premise MS SQL на AWS MySQL. Использовался Linq2Sql (тогда EF ещё не было). Нашёл два коннектора, опен-сорс и от devart. Опенсорсный не завёлся, девартовский сразу заработал. Данные перенёс сравнительно легко, а вот процедурки пришлось переписывать. Причём отчасти и логику, потому что оптимизации в мускле работали как-то иначе. Но в целом управился за пару-тройку дней.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий