| « RMDC... | Быстрый и легкий foreach со ссылкой на элемент массива в PHP » |
MSSQL - убожество
Прочее ITКакое же оно убожество, этот MSSQL. Меня вообще удивляет, как ТАКОЕ может продаваться.
(детали - под катом, сразу предупреждаю - на вкус и цвет фломастеры разные, это - сугубо личное мнение человека, которому приходится работать сразу под несколькими платформами)
...
Во-первых, оно не умеет LIMIT. Во-вторых, оно не умеет нормально делать DISTINCT, не теряя порядка исходных строк. Да, можно долго убеждать, что нужен ORDER BY или что это "для оптимизации". Но. Есть одно "но". MySQL в таком случае работает нормально, строки при DISTINCT рандомно не переупорядочивает, и, что главное - работает раз в 5-10 шустрее, даже на больших базах.
А ORDER BY в конкретном запросе вставить некуда - DISTINCT просто не позволяет выбрать дополнительные поля так, чтобы еще и по ним не было уникальности.
В третьих, INNER JOIN работает тоже через задницу. В MySQL все правильно - выбирает строки из первой таблицы, к ним присоединяет строки из второй. MSSQL - дает вообще рандомную комбинацию - то первую со второй, то вторую с первой. Дооптимизировались. Опять же, ORDER BY по первой таблице сделать не получается, GROUP/HAVING тоже приткнуть некуда.
В-четвертых, эта дрянь не умеет CONCAT - приходится использовать синтаксис с +, и нормального автоматического преобразования чисел заданного формата в строку для сложения в ней тоже нет - STR нормальным методом считать сложно.
В-пятых, ЭТО не умеет даже TRIM, приходится писать LTRIM и RTRIM. Почему в ЭТОМ все пишется на хранимых процедурах в десятки строк при таком убожестве в синтаксисе - вполне понятно.
Да, может быть я пытаюсь решить на MSSQL непосильную ему задачу. Но - спрашивается - нафига он такой тогда вообще нужен. Тем более - за такие деньги.
Вердикт - для конкретной производственной задачи - закопать. Выгрузка данных в локальный массив и обработка в локальном массиве.
Для больших систем? Еще на нем крутится биллинг в одной уважаемой организации. Уже купили 4x4 систему под него с невъ*** количеством памяти и SAS R1+0 - ему все равно мало. Для своей сопроводительной системы делаю кешированную выгрузку данных в MySQL на обычный средненький сервер, и уже там все разбираю под отчеты пользователям (личный кабинет) - если брать прямо с MSSQL - тормозит безбожно. Закапывать не получится, увы, биллинг должен быть сертифицирован... сюда все и упирается.
Кто-то скажет - а вы пробовали X (Y, Z) на MySQL? Я "пробую" на MySQL базу RADIUS для приличного числа пользователей. С различными статистическими выборками и прочим интересным, без LIMIT вообще не обойтись. Пока что не подводило ни разу, онлайн-бэкап на базе фиксации транзакций - тоже весьма приятная штука, позволяющая обходиться без извращений. Если MSSQL скормить такую базу - на 99% уверен, что оно сдохнет, даже не начавшись. Хотя бы из-за того же LIMIT'а (который не только с 1 записи бывает, но и с 1000000'ной, к примеру).
P.S. Попутно обнаружилось что оно не умеет и INSERT IGNORE или хотя бы какого-то аналога. Последняя попытка обойти неумения MSSQL канула вместе со всеми остальными. Осталось только обрабатывать в приложении.
Трекбек адрес этой записи
URL трекбека (щелкните правой кнопкой мыши и скопируйте ссылку)
Стандартный запрос аля - INSERT * INOT...
Строк - 3144;
MSSQL - 0.14485 сек.
MySQL - 0.0786 сек.
Результат на лицо.
MySQL хорош для использования с небольшими web-сайтами, написанными на языках типа PHP, но если создавать что-то более серьезное и требовательное к доступности данных и выбор встанет между MSSQL и MySQL, то - MSSQL (наличие процедур, функций, триггеров, возможность использования CLR сборок, полнотекстовый поиск с поддержкой русского языка, линковки серверов, репликация, кластеризация, зеркалирование, планировщик, почтовый агент и т.д., а также более развитый SQL - T-SQL, поддержка использования курсоров)
MySQL LIMIT оптимизирует посредством использования индексов (естественно, в тех запросах, где индексы актуальны - а иных и быть не должно).
Производительность такого изврата, как ROW_NUMBER+TOP+подзапрос отличается в разы или сотни раз - в зависимости от положения начала запроса внутри результата, поскольку подзапросы теряют возможность использования индексов - чем дальше, тем страшнее.
>>> Насчет скорости вставки данных - помимо мощности сервера неплохо было бы учесть тип таблиц в MySQL и режим восстановления БД в MSSQL.
Мы в наших задачах используем InnoDB, поскольку нам нужна надежность + транзакционность. База оперирует несколькими гигабайтами данных в реальном времени (сессии и запросы абонентов) + постоянная работа системных скриптов.
Более того, совсем недавно перешли для жизненно важных данных реального времени на MySQL NDB Cluster - у MSSQL такого просто нет в природе - есть репликация, но она не дает синхронности обновлений между серверами. Есть MSCS, но она не дает возможности параллельного использования нескольких серверов, только хотсвап.
>>> MySQL хорош для использования с небольшими web-сайтами, написанными на языках типа PHP, но если создавать что-то более серьезное и требовательное к доступности данных
Для начала ответьте: сеансовые запросы абонентов (RADIUS), учет данных (запросы на статистику сеансов и изменение тарифных опций в любой удобный момент времени) от нескольких тысяч абонентов, финансовая статистика, обработка тарифной логики в связке с оборудованием, поддерживающим эти тысячи абонентов - это не серьезная, и не требовательная задача?
>>> Репликация, кластеризация, зеркалирование, планировщик, почтовый агент.
Каждая функция должна полноценно реализовываться своим специализированным ПО (а не всё по чуть-чуть одним монструозным комбайном) - это залог здоровья, отказоустойчивости системы и спокойствия администратора. T-SQL - это, конечно, здорово - но покажите мне уже LIMIT или INSERT IGNORE/INSERT DELAYED в этом "развитом SQL".
И проблем у этого комбайна тоже по горло - меня убивал частый deadlock на транзакциях Dynamics AX в связке с SQL Server 2005, даже тайм-аут не спасает. Можно конечно сказать - софт написан криво. Может и криво, но почему, черт возьми, не срабатывает тайм-аут, когда транзакции на запись блокируются длинной и тяжелой выборкой в хранимой процедуре? Звонок в поддержку не дал ничего - предложили заплатить столько, что было решено от поддержки отказаться.
По опыту - Oracle удобен для огромного размера решений, которые уже едва ворочаются на малых движках. Для небольших решений лучше MySQL / PostgreSQL не найти, для средней масштабируемости - NDB Cluster.
При том, попытка выполнить эти запросы над аналогичной базой в MSSQL приводит к "подвисанию" транзакции на неопределенное время, так, что проще перетащить огромные таблички в MySQL и работать с ними там.
Для примера - попробуйте выполнить запрос с кучей JOIN'ов, с ответом в 100000-1000000 записей в 5-6 таблицах с суммарным размером 2-8 гигабайт, и сделать над ним LIMIT x,y (выбрать записи с x по y, и только их)... Если у вас получилось быстрее, чем за 1 секунду - значит это не MSSQL. Если у вас получилось и это MSSQL - то вас ждет UNION с таким же запросом, + GROUP BY за пределами UNION... Если у вас получилось и это - ... я вам не верю :)
Единственное, чем удобен MSSQL - это хранимыми процедурами. Однако в MySQL они тоже появились, и, хоть и далеки от совершенства, но использоваться уже могут. Не хватает только полноценных триггеров, хотя и это, думается мне, вопрос времени.
Не через задницу, а как оптимизатор выберет. По всему видно, что автор не работает плотно с mssql, потому что не знает даже о хинтах, о методах, которые использует mssql при объединении.
mysql и mssql действительно для разных задач, а выборка туевой хучи записей - это не пример
Сначала читай что такое inner join. Неправильно у него отрабытывает, у тебя результаты MySql Шаблон для всего.
Хотя - согласен, в MySQL оптимизатор запросов тоже может перекидывать JOIN'ы туда-сюда, но делает это более предсказуемо. Этой предсказуемостью можно здорово пользоваться, когда счет идет на сотни запросов в минуту.
Я имел в виду запросы на таблице, которая не изменялась. В MSSQL _последовательные_ одинаковые запросы на _неизменной_ таблице могут выдавать каждый раз разную последовательность JOIN'ов. Когда их 2 - заметно слабо. Когда их 10-12... индийский рандом.
к тому же уже давно заметил, что простые последовательные запросы выполняются быстрее продуманного мега запроса из кучи join-ов. из-за меньшего использования оперативки причём на всех типах баз данных. в таких случаях даже использование временных таблиц оправдано.
У MySQL только один серьезный недостаток ныне: убогие хранимые процедуры (а также триггеры и иже с ними).
Зато у MySQL есть то, чего MSSQL в принципе не снилось никогда - NDB Cluster. Вещь, правда, крайне специфичная, и имеет ряд серьезных ограничений, но в отдельных задачах незаменима - разве что Oracle DBMS как вариант, но стоимость несопоставима.
А что до использования простых запросов вместо JOIN - это хорошо, пока таблицы небольшие. А когда JOIN'ишь три-четыре таблицы по миллиону записей каждая, выбирая в сухом остатке 3-4 тысячи строк, без JOIN'ов не обойтись.
Мне кажется это вообще нужно только для постраничной разбивки данных на сайте.
>>Во-вторых, оно не умеет нормально делать DISTINCT, не теряя порядка исходных строк.
Это соответствует стандартам, так что на нестандартную фичу в MySql я бы закладываться не стал. Вдруг в новых версиях это уберут? Для переносимости на уровне исходников order by ставить-таки придется.
>>В третьих, INNER JOIN работает тоже через задницу. В MySQL все правильно - выбирает строки из первой таблицы, к ним присоединяет строки из второй. MSSQL - дает вообще рандомную комбинацию - то первую со второй, то вторую с первой.
Есть пример этого запроса? Наверное запрос написан с такой ошибкой, что получается декартово произведение вместо соединения. INNER JOIN должен работать одинаково в двух СУБД.
>>В-четвертых, эта дрянь не умеет CONCAT - приходится использовать синтаксис с +...
Ну, это уж совсем каприз, но можно с помощью UDF решить на ура.
>>и нормального автоматического преобразования чисел заданного формата в строку для сложения в ней тоже нет - STR нормальным методом считать сложно.
Есть CAST и CONVERT
>>В-пятых, ЭТО не умеет даже TRIM, приходится писать LTRIM и RTRIM.
Не самое страшное, и на тоже UDF пара строк
CREATE FUNCTION Trim( @str1 varchar(255) )
RETURNS varchar(255)
AS BEGIN
RETURN Rtrim(Ltrim(@str1))
END
Потом биллинг все-таки берет объемом данных а не сложностью структуры. Биллинг On-line мы тоже делали на MySQL и думаем вообще некоторые вещи сделать на текстовых файлах с парсером. А вот стратегическое планирование фармацевтического холдинга - где много разработчиков в разных городах, 1500 таблиц и где нужны отладчик, диаграммы + CASE средства, MySQL никак никак не подошел.
Совершенно согласен. У нас компания, занимающаяся ритейлом. Фронт-офис организован на MySQL, хранится каждый чек, доступ к чеку по индексу происходит за доли секунды, на большом объеме данных с относительно несложной реляционной структурой MySQL показывает себя хорошо даже на нескольких сотнях миллионов записей, главное не на настольном компьютере это все крутить, конечно.
А вот back-office у нас предусматривает наличие отличающихся друг от друга по структуре предприятия филиалов и возможные локализационные поправки к бизнес-процессу. Структура базы данных значительно сложнее, чем на front-офисе, больше тысячи таблиц, связи порой по несколько десятков таблиц, MySQL тут бы давно загнулся, а вот кластер на Oracle справляется с легкостью. Каждая СУБД предназначена для своей ниши, для решения своих задач.
В защиту Postgres хочу сказать, что текущая версия очень даже хорошо себя показывает на сложных многотабличных запросах, единственное, что пока не научился "договариваться" с ее оптимизатором, кажется шаманством заставить использовать индексы движком Постгрес, но это исключительно из за поверхностного знакомства с этой СУБД. :-)
P.S.: напоследок, длиной запросов в символах меряются только подростки от программирования, можно написать огромный запрос и положить любую, даже самую хорошую СУБД. Не надо больше про несколько десятков 80-символьных запросов, тем более что это еще не показатель уровня запросов в сложных корпоративных бизнес-системах.
Кстати, а ведь MySQL при использовании Limit СТАРТ, КОЛИЧЕСТВО до позиции start переходит тупым сканированием результата выполнения запроса, чем больше значение СТАРТ, тем дольше возвращается результат, даже если КОЛИЧЕСТВО = 10 строкам. Когда начальная позиция результата запроса равна 10 миллионов записей, ждать несчастные десять строчек становится весьма утомительным занятием.
Ну и это, правильно тут советуют, что полагаться на то, что MySQL всегда вернет одинаковую последовательность строк в результате запроса без сортировки -- это полагаться на конкретную реализацию, в ANSI SQL ни в одном нет таких требований, и не факт, что однажды MySQL в целях какой нибудь оптимизации выполнения запроса не начнет возвращать хаотично перетасованный набор после выполнения запроса, не использующего сортировку явно.
Нет. Можно узнать, откуда Вы такой бред почерпнули?
LIMIT в MySQL использует индексы (range scan), если запрос написан правильно. Если в Вашем случае это не так - стоит поюзать EXPLAIN, и найти, почему MySQL не использует индексы.
>>> Ну и это, правильно тут советуют, что полагаться на то, что MySQL всегда вернет одинаковую последовательность строк в результате запроса без сортировки -- это полагаться на конкретную реализацию
Мне не важен сам порядок строк. Мне важна предсказуемость последовательности выборки. Конкретные строки могут каждый раз идти в разном порядке, важно, чтобы само объединение более-менее группировало строки. При этом моей конкретной реализации моей конкретной задачи совершенно не поплохеет, если строки пойдут вразнобой, но работать оно будет несколько дольше. Если проще - я использую предсказуемость выборок для оптимизации расчета, потому что расчет параметров по нескольким Гб входных данных (даже с учетом кеширования, etc.) - операция не быстрая.
Полностью согласен. Но такое впечатление, что MSSQL как раз таки остается без ниши, ибо на большие структурированные таблицы, а также малые проекты - MySQL, на множество плохо структурированных ("корпоративный" вариант) - Oracle. А на MSSQL остаются только те, кто привязан к микрософту, и не в состоянии шагнуть в сторону.
Есть еще NDB Cluster. Эта вещь спасает телекомщиков (и меня в т.ч.) уже не первый год, ибо оно незаменимо там, где очень важна отказоустойчивость вкупе с шустростью обработки сравнительно небольших таблиц.
Этот "бред" я почерпнул из опыта. Вот сейчас взял и тупо сделал селект из одной таблицы, по индексу. Результат времени выполнения разный, если взять limit 1, 10 и limit 10 000 000, 10 (форматирование числа произвел специально для облегчения восприятия информации). Версия MySQL-сервера 4.0.3.
По поводу Limit по индексам, поверю, если поделитесь ссылочкой.
>> Мне не важен сам порядок строк.
Это я понял, что Вам не важно, какая строчка за какой будет следовать. Но мои слова ведь абсолютно коррелируются с Вашими о предсказуемости последовательности выборки.
А о том, что предсказуемость выборки используется для оптимизации -- это не только в MySQL применяется, но и в том же PostgreSQL, правда там рекомендуется, все таки, предварительно сортировать.
К сожалению, не знаю, в какой версии сделали... но 4.0.3 - это уже каменный век, практически... Уже 5.5 на дворе, до него были 4.1 и 5.0. Оптимизатор сильно допиливали в 4.1, скорее всего в этой ветке появилась оптимизация LIMIT, но надо уточнять.
Да, и очень важно еще - MyISAM у Вас или InnoDB. Совершенно разные движки, вопрос оптимальности каждого - отдельная тема. MySQL в этом плане еще очень хорош тем, что дает гибкость выбора.
>>> А о том, что предсказуемость выборки используется для оптимизации -- это не только в MySQL применяется, но и в том же PostgreSQL
Как, в общем-то, и в любой сложной системе, мне кажется. Фигня с MSSQL в этом плане заключается в том, что выборка каждый раз практически рандомна - наверняка используют стохастические алгоритмы вкупе с бинарным слиянием между потоками. У такого подхода есть свои прелести (особенно маркетинговые, вида невозможности различить неоптимальность запроса и особенность движка, ибо процесс каждый раз идет по разному), но для оптимизации расчетов это - смерть.
по моему субъективному опыту, его ниша там, где на начальном этапе его внедрили и на нем спроектировали БД :-)
Мне приходилось видеть MSSQL не в качестве СУБД для 1С на предприятии, где приложения были написаны на Access, а 10 миллионов записей в таблице админ считал катастрофой. Но там на момент 2006го года стоял сервер 7.0
Как-то вот опыта использования по-взрослому этой СУБД я не встречал, по моему, опять же субъективному, мнению это система для среднего бизнеса, тем более, что на фоне прочих коммерческих СУБД MSSQL относительно дешевая.
Согласен с Вами :)
Я встречал опыт использования этой СУБД "по-взрослому" - Microsoft Dynamics Ax, большая филиальная сеть, централизованная DBoVPN (VPN шустрые).
Постоянные тормоза во время тяжелых отчетов (большая база, большие выборки, блокировки), зависающие намертво транзакции (лечилось только ручным сбросом, потом написали скрипт), один раз - потеря данных в момент одновременной активной работы пары сотен пользователей (потребовалось разворачивание бэкапа - была нарушена внутренняя структура данных, порваны связи, хотя эти операции не должны были пройти именно из-за Foreign Key).
В итоге так оно все как-то кое-как и работает, я уже давно из этой организации ушел на более рыбное/хлебное место, и не завидую тому, кто с этой системой сейчас мучается.
так это же в девичестве Аксапта которая, она что ли, родимая? :-D
На одном из предприятий, где я работал семь лет назад, ее чуть не внедрили, вовремя отказались. В итоге сейчас она стоит в одном из филиалов, но уже на оракле. :-)
Ога, она самая. Вот что существует версия под оракл - не знал :)
RADIUS для тысяч пользователей и гиг данных - это в масштабах СУБД - мелкая задача.
MSSQL даже на препроцессинге данных (а он достаточно сложный, не просто SELECT по ключу - множество связанных таблиц и операций) уходит в ступор на несколько суток каждый месяц, ни о какой реалтаймовости при различных операциях и речи нет, эта система для реалтайма не используется в силу её неповоротливости.
MySQL на аналогичной же задаче отрабатывает данные за 11 месяцев (один раз надо было сделать пересчёт для сверки) чуть более, чем за сутки, позволяя при этом в штатном режиме работы телефонистам постоянно мониторить трафик по ряду параметров + разыскивать любую необходимую последовательность звонков по массе сложных критериев в пределах месяца менее, чем за 30 секунд, и абонентам - выбрать свои звонки в течение 1-2 секунд.
Имея контакты с серьёзной массой организаций различной направленности, я пока ещё не видел ни одной мало-мальски сложной задачи с большИм объёмом данных, с которой MSSQL справился бы нормально, не вызывая тормозов в отработке. Если видели - приведите. Ниша MSSQL - "бизнес-приложения", в которых объём данных достаточно мал, чтобы оно не тормозило, и в которых быдлокод в хранимых процедурах не очень сказывается на производительности. Хотя, в последнее время крупные торговые сети сталкиваются с жёстким ухудшением времени обработки данных для отчётов, и переходят на Oracle.
У меня у самого биллинг (ISP) на MySQL, база данных - 300+ Гб (мы обязаны хранить RADIUS-аккаунтинг последние 2 года, потом сворачиваем до месяцев).
Есть также Web-магазин, который, к сожалению, должен работать с MSSQL, т.к. 1С:Предприятие связано с последним. О да, то еще ТОРМОЗНУТОЕ УБОЖЕСТВО этот M$SSQL.