пятница, 15 марта 2013 г.

Это приятное чувство "а я ведь говорил"

Вспомнилось.

На одной из прошлых работ столкнулся с любопытной ситуацией различия работы серверов баз данных MySQL и MS SQL.
Вкратце и упрощенно, клиенты часто получали неприятность отказа программы при использовании определенных тяжелых запросов с помощью внутренней системы поиска.
Внутри все сводилось к запросу вида
SELECT DISTINCT [smthng1] FROM (множество_1) WHERE [smthng2] NOT NULL AND EXISTS (множество_2)
Не буду углубляться в сложности выборки обоих указанных множеств - это не существенно. Сложные. Поля из нескольких таблиц.

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

Главный симптом проблемы проявлялся "выбрасыванием" исключения достижения максимального допустимого времени для сокетного соединения между программой и сервером для запроса.
Сервер баз данных не мог справится даже на не очень уж большой базе данных за пять отпущенных ему минут с запросом.

Разбор полетов показал, что эффективнее разбить запрос на две части, и с помощью java перебрать совпадения множеств, чем ждать пока MySQL обработает EXISTS.
Что ж, решение было внедрено и отправлено клиенту.

Но внезапно оказалось, что у клиента MS SQL и его проблему патч не решил.
Ощущение собственной правоты подогрело душу.
Клиент своим отказом отсрочил полноценное решение проблеммы.

Но это не было концом истории.

Дамп базы MS SQL для препарирования мы все-таки получили.
Но потом оказалось, что никаких проблем с EXISTS у запроса нет.
Недоразумения для MS SQL связаны с DISTINCT.

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

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

Выводы, они же советы.

  1. Добивайтесь максимального совпадения рабочей среды и среды разработки.
  2. Осторожно с  EXISTS в MySQL.
  3. Осторожно с DISTINCT в MS SQL.
Дальше надо бы подкрепить примерами на тестовой базы на чистом и свободном проекте, но уж очень лень. "Я просто оставлю здесь это"...