Здравствуйте, Cyberax, Вы писали:
C>Как ни странно, Google вот примерно так и сделал.
На гугловых задачах ACID-ность не нужна, им MySQL в самый раз. У гугла все-таки уникальная задача, не следует их сомбреро натягивать на всех хуанов в округе.
IB wrote: > C>Как ни странно, Google вот примерно так и сделал. > На гугловых задачах ACID-ность не нужна, им MySQL в самый раз. У гугла > все-таки уникальная задача, не следует их сомбреро натягивать на всех > хуанов в округе.
MySQL, кстати, давно уже ACID. А его последние фичи с share-nothing
кластеризацией — вообще позволяют во многих случаях успешно соперничать
с Oracle/MSSQL.
Здравствуйте, Cyberax, Вы писали:
C>MySQL, кстати, давно уже ACID.
Гы. Его ACID, это главная деталь вечного двигателя — вечный тормоз. Его использовать-то толком нельзя.
C> А его последние фичи с share-nothing кластеризацией — вообще позволяют во многих случаях успешно соперничать C>с Oracle/MSSQL.
Ну да, когда транзакционность не нужна.
IB wrote: > C>MySQL, кстати, давно уже ACID. > Гы. Его ACID, это главная деталь вечного двигателя — вечный тормоз. Его > использовать-то толком нельзя.
Странно, многие почему-то так вполне успешно его используют. MySQL
Enterprise пользуется вполне себе неплохим спросом.
> C> А его последние фичи с share-nothing кластеризацией — вообще > позволяют во многих случаях успешно соперничать > C>с Oracle/MSSQL. > Ну да, когда транзакционность не нужна.
Блин, MSSQL уже пять лет как транзакции поддерживает. В их кластерной
системе как раз нетранзакционный движок вообще не работает. Ты вообще
кроме MS что-нибудь смотришь?
Здравствуйте, Cyberax, Вы писали:
C>Странно, многие почему-то так вполне успешно его используют.
Конечно используют на хомяках.
C>MySQL Enterprise пользуется вполне себе неплохим спросом.
Там где транзакции не нужны.
C>Блин, MSSQL уже пять лет как транзакции поддерживает.
MySql? Фигово он их поддерживает. Обоими своими движками и беркли и финской поделкой.
C> В их кластерной системе как раз нетранзакционный движок вообще не работает.
Да там и транзакционный не очень.
IB wrote: > C>Странно, многие почему-то так вполне успешно его используют. > Конечно используют на хомяках.
Статистику в студию.
> C>MySQL Enterprise пользуется вполне себе неплохим спросом. > Там где транзакции не нужны.
Мда. А MSSQL используют там, где администраторам лень ставить нормальную
БД типа Oracle или Postgres.
> C>Блин, MSSQL уже пять лет как транзакции поддерживает. > MySql? Фигово он их поддерживает. Обоими своими движками и беркли и > финской поделкой.
В чем фиговость? "Агласите весь список, пжалуста" (c) фильм.
> C> В их кластерной системе как раз нетранзакционный движок вообще не > работает. > Да там и транзакционный не очень.
Чем "не очень"? Полный ACID, с поддержкой XA.
Здравствуйте, Cyberax, Вы писали:
C>Статистику в студию.
В гугле поищи.
C>А MSSQL используют там, где администраторам лень ставить нормальную C>БД типа Oracle или Postgres. Постгри тут тоже очень кстати. )
C>В чем фиговость? "Агласите весь список, пжалуста" (c) фильм.
Тормозами и глюками.
C>Чем "не очень"? Полный ACID, с поддержкой XA.
Вот именно что полный, только очень медленный и не стабильный.
Здравствуйте, Flying Dutchman, Вы писали:
FD>На странице 12 читаем:
FD>
FD>...note that the PRIMARY KEY and FOREIGN KEY clauses correspond to business rules...
FD>(...отметим, что предложения PRIMARY KEY и FOREIGN KEY относятся к бизнес-правилам...)
FD>или немного ранее
FD>
FD>Indeed, foreign key constraints in particular are an important case of
FD>business rules in general.
FD>(В самом деле, ограничение по внешнему ключу является частным случаем бизнес-правила.)
FD>Так что ограничение целостности являются бизнес-правилами.
Почти прав. Только ограничения целостности не всегда являются бизнес-правилами. Допустим:
1. Сообщение не может быть без адресата.
Как бы все прекрасно, делаем foreign key на адресат, и можно почти считать что мы выполнили данное бизнес-правило. foreign key — есть бизнес-правило.
Но тут появляется второе требование.
2. При сохранении сообщение, в случае если адресат не заполнен, пользователю должен быть предложено заполнить адресат.
Oops. Посылать на сервер неликвидные данные в принципе можно. Получишь оттуда ошибку (нормальное получение ошибки еще та песня) и покажешь форму выбора адресата. Только по правильному нужно все решать на уровне клиента и бизнес-логики клиента без открытия транзакции. И получается, что клиент а не БД выполняет не только бизнес-логику. А foreign key — как таковой является только логикой хранения данных, может и желательной вещью, но необязательной.
Что же касается PK — то в большинстве случаев он вообще суррогат. И бизнес-сущностью его фиг опишешь.
Здравствуйте, Cyberax, Вы писали:
C>>>Зачастую просто написать тупой императивный код, чем громоздить запросы C>>>и работать с курсорами. P>>Курсоры идут в сад! А вот "запросы" — это то, что умеет "переваривать" СУБД гараздо лучше, чем самопальный императивный код на апп. сервере. C>Как ты предлагаешь _нормально_ без курсоров работать с понятиями "предидущий ряд результата"/"предидущая точка изменения"?
В этом случае можно прекрасно обойтись без курсоров (другое дело, что это
как раз та область применения SQL, которая сложна для понимания программистов,
которые пишут на процедурных/императивных языках).
Курсоры вообще нужны в очень ограниченном числе случаев, например:
1. БД спроектирована неправильно. Например, вместо того чтобы
хранить заказы и/или другие данные всех клиентов в одной таблице, делается
отдельная таблица для каждого клиента.
2. К каждому элементу из результата запроса нужно применить операцию,
отсутствующую в SQL, например, вызвать хранимую процедурую. Или,
например, "получить список всех соединений к базе данных A и для
каждого соединения выполнить команду kill". (В Transact SQL часто
можно в подобных случаях обойтись без курсора при помощи
использования денормализации списков + динамического SQL).
3. Иногда бывает, что решение на основе курсора быстрее, чем решение
на чистов SQL (в случае использования запросы на основе тэта-соединений (theta-joins)).
Например, задача вычисления нарастающих итогов (running totals) часто решается
быстрее на основе курсора.
4. Другие редкие случаи, например, обработка иерархических струкур. (Однако,
напрмер, при использовании Transact SQL курсор в этом случае не нужен).
Но в подавляющем большинстве случаев задачу можно решить без использования курсоров и решение
на SQL получается короче.
Здравствуйте, Cyberax, Вы писали:
C>Flying Dutchman wrote: >> Зато языки хранимых процедур обладают большими возможностями для работы >> с реляционными данными. C>Работа с реляционными данными в большинстве случаев сводится к "сделать C>запрос". Это прекрасно можно сделать без хранимых процедур.
Можно, но делать запросы в коде, скажем на C#, гораздо неудобнее, чем
в хранимых процедурах, потому что
1. SQL в хранимых процедурах статический, а в программе на C# динамический.
Это означает, что в ХП ошибки в SQL-коде видны сразу при компиляции, а в
SQL-запросе в C#-программе — только на этапе выполнения программы.
Это затрудныет отладку и тестирование.
В некоторых системах существует Embedded SQL (например, в среде
IBM OS-360/390 при работе с PL/1 + DB2 это было еще 20 лет назад). То есть
запросы пишутся на SQL прямо в тексте программы на процедурном языке, потом
программа обрабатывается препроцессором, который делает проверку ошибок в SQL
(и соответствия используемых таблиц и столбцов реальной структуре БД)
и уже потом программа компилируется.
Но в .NET это не реализовано.
2. При изменениии структуры таблиц в БД соответствующий код в ХП перестает
компилироваться и сразу видно, где нужно внести изменения. В программе
на C# нужно вручную просмотреть все тексты запросов.
3. В языке хранимых процедур присутствуют средства, которых нет в C#.
Например, в Tкansact SQL можно использовать временные таблицы и табличные
переменные. Или использовать в SELECT функции, созданные на Transact SQL.
4. Нужно писать дополнительный код для передачи параметров в запросы
(либо переводить используемые значения в текстовый вид) и
следить за предотвращением ошибок типа SQL Injection.
Исходя из этого, во многих организациях действует правило, согласно которому
в клиентской программе вообще не должно быть никакого кода на SQL, за
исключением:
1. Запросов, снегенерированных автоматически — например, при помощи ORM.
2. Сложных запросов, которые строятся динамически на основе данных,
введенных пользователем в форме.
Я также являюсь сторонником этого правила.
С>А тут еще и C>LINQ подкатывает, который сведет на нет большую часть "преимуществ" БД.
О преимуществах LINQ пока еще рано говорить — слишком молодая технология.
К тому же стремление авторов lINQ обеспечить возможность выполнения
запросов из разных источников вполне может оказаться попыткой пойти двумя
ногами в две разные двери .
C>Ну и я не говорю про ORM.
ORM, конечно, вещь очень полезная, но не избавляет полностью
он необходимости писать запросы руками.
ORM обычно позволяет создать набор классов, инкапсулирующих в себя
структуру таблиц БД и отношений между ними и затем использовать
их для манипуляции данных в БД.
В первую очередь можно легко автоматизировать CRUD-операции (
от слов Create-Read-Update-Delete), имеются в виду такие
базовые операции как "Прочитать все данные из таблицы",
"Прочитать/изменить/удалить одну запись из таблицы с соответствующим
значением первичного ключа или уникального индекса" или "добавить
новую запись в таблицу". Также автоматизируются более сложные
операции, например "Для двух таблиц, связанных отношением 1:M,
для определенной записи в родительской таблице вернуть все
соответствующие данные из дочерней таблицы".
ORM предыдущего поколения (например, Olymars) создавали для
этих целей хранимые процедуры в базе данных (что было не совсем
удобно, потому что база данных засорялась множеством мелких ХП).
Современные ORM (например, LLBLGen) используют методику динамической генерации
SQL в процессе выполнения программы.
Например, я использую LLBLGen Pro. Он создает классы и методы,
при помощи которых можно манипулировать данными в базе данных
без явного использования SQL. Сгенерированные классы и методы можно
использовать таким, например, образом:
OrdersCollection cOrders = new OrdersCollection();
cOrders.GetMulti(new PredicateExpression(OrdersFields.ExportDate == DBNull.Value));
Это означает: "Выполнить запрос
select *
from Orders
where ExportDate is null
и занести результат в коллекцию cOrder".
при выполнении этого C#-кода происходит генерация SQL-кода,
который передается на выполнение базе данных.
Теоретически любой SQL-запрос можно записать в подобной форме.
Но только теоретически.
Для простых запросов это работает, но стоить немного усложнить запрос
(добавить несколько условий в Where, соединить несколько таблиц или
выполнить два запроса в одной транзакции), как код становится
совершенно нечитаемым.
То есть на практике ORM может помочь избавиться от 80% SQL-кода,
но сложные запросы по-прежнему проще реализовывать в хранимых процедурах.
>> P>>По меньшей мере странно обрабатывать данные в реляционным хранилище >> языком, не предназначенном для этого. >> C>По меньшей мере странно использовать *хранилище* для обработки данных. >> База данных — это не просто хранилище данных, а хранилище данных + >> хранилище бизнес-правил + устройство обработки данных. C>Нет. База данных — это именно хранилище, на которое многие пытаются C>навернуть того, что там не должно быть.
База данных — это, как минимум, структура данных + сами данные + констрейнты.
Flying Dutchman wrote: > C>Как ты предлагаешь _нормально_ без курсоров работать с понятиями > "предидущий ряд результата"/"предидущая точка изменения"? > В этом случае можно прекрасно обойтись без курсоров (другое дело, что это > как раз та область применения SQL, которая сложна для понимания > программистов, которые пишут на процедурных/императивных языках).
А можно пример как? Мне нужно при работе хранить множество точек
изменений значений или функции от значения.
> Курсоры вообще нужны в очень ограниченном числе случаев, например: > 1. БД спроектирована неправильно. Например, вместо того чтобы > хранить заказы и/или другие данные всех клиентов в одной таблице, делается > отдельная таблица для каждого клиента.
Нормализовано, до третей нормальной формы.
> 3. Иногда бывает, что решение на основе курсора быстрее, чем решение > на чистов SQL (в случае использования запросы на основе тэта-соединений > (theta-joins)). > Например, задача вычисления нарастающих итогов (running totals) часто > решается быстрее на основе курсора.
Theta-join'ы слишком ограничены. C running totals — все просто. А ты
попробуй написать запрос, который пронумерует dupe'ы в базе данных.
Императивный код для этого будет работать O(N) времени (ну O(N*log N)).
> Но в подавляющем большинстве случаев задачу можно решить без > использования курсоров и решение на SQL получается короче.
Меня эти случаи не подавляют — почему-то они как раз у меня толпами летают.
Здравствуйте, Flying Dutchman, Вы писали:
FD>1. SQL в хранимых процедурах статический, а в программе на C# динамический. FD>Это означает, что в ХП ошибки в SQL-коде видны сразу при компиляции, а в FD>SQL-запросе в C#-программе — только на этапе выполнения программы. FD>Это затрудныет отладку и тестирование.
Это исправляется нормальными инструментами. Например:
Я специально добавил ошибки — установку несуществующего параметра и несуществующее поле. Как видишь, IDE мне их вполне нормально показала и подсветила. Также обрати внимание на подсветку синтаксиса. При редактировании, естественно, работает автокомплит и рефакторинг.
FD>2. При изменениии структуры таблиц в БД соответствующий код в ХП перестает FD>компилироваться и сразу видно, где нужно внести изменения. В программе FD>на C# нужно вручную просмотреть все тексты запросов.
См. предидущий пункт.
FD>3. В языке хранимых процедур присутствуют средства, которых нет в C#. FD>Например, в Tкansact SQL можно использовать временные таблицы и табличные FD>переменные. Или использовать в SELECT функции, созданные на Transact SQL.
Единственный плюс для хранимых процедур.
FD>4. Нужно писать дополнительный код для передачи параметров в запросы FD>(либо переводить используемые значения в текстовый вид) и FD>следить за предотвращением ошибок типа SQL Injection.
SQL injection вполне возможен и при вызове хранимых процедур.
FD>Исходя из этого, во многих организациях действует правило, согласно которому FD>в клиентской программе вообще не должно быть никакого кода на SQL, за FD>исключением: FD>1. Запросов, снегенерированных автоматически — например, при помощи ORM. FD>2. Сложных запросов, которые строятся динамически на основе данных, FD>введенных пользователем в форме.
Вот эти мне ОЧЕНЬ не нравится. Только зря увеличивается число сущностей — в крайнем случае можно манипуляцию в отдельный DAL вынести.
C>>Ну и я не говорю про ORM. FD>ORM, конечно, вещь очень полезная, но не избавляет полностью FD>он необходимости писать запросы руками.
См. пункт 1
FD>Например, я использую LLBLGen Pro. Он создает классы и методы, FD>при помощи которых можно манипулировать данными в базе данных FD>без явного использования SQL. Сгенерированные классы и методы можно FD>использовать таким, например, образом: FD>То есть на практике ORM может помочь избавиться от 80% SQL-кода, FD>но сложные запросы по-прежнему проще реализовывать в хранимых процедурах.
Это просто в .NET нет нормальных ORM Для Java есть Hibernate и Toplink — сейчас, пожалуй, только сверхсложные аналитические запросы не получается нормально на Hibernate Query Language писать.
C>>Нет. База данных — это именно хранилище, на которое многие пытаются C>>навернуть того, что там не должно быть. FD>База данных — это, как минимум, структура данных + сами данные + констрейнты.
Естественно. С этим я не спорю — у баз данных хранение данных и проверка констрейнтов получаются очень хорошо.
IB wrote: > C>Статистику в студию. > В гугле поищи.
Можно ключевые слова?
> C>А MSSQL используют там, где администраторам лень ставить нормальную > C>БД типа Oracle или Postgres. > Постгри тут тоже очень кстати. )
Ну ты же делаешь нелепые необоснованые заявляения. Чем я хуже?
> C>В чем фиговость? "Агласите весь список, пжалуста" (c) фильм. > Тормозами и глюками.
"Агласите весь список, пжалуста" (c) фильм.
> C>Чем "не очень"? Полный ACID, с поддержкой XA. > Вот именно что полный, только очень медленный и не стабильный.
Да??? По моим тестам MySQL на стоковом железе в кластере выигрывает у
ВСЕХ крупных серверов (тестировался Oracle, Postgresql+PgCluster, MSSQL)
на разумных операциях.
Что, собственно, неудивительно — NDB (кластерный движок в MySQL)
придумывался для high-perf телекомовских приложений.
Здравствуйте, Cyberax, Вы писали:
C>Можно ключевые слова?
Сам не справляешься?
C>Ну ты же делаешь нелепые необоснованые заявляения. Чем я хуже?
Тем что я не делаю нелепых и необоснованных утверждений. .
C>"Агласите весь список, пжалуста" (c) фильм.
Тормозами и глюками.
C>Да???
Угу.
C> По моим тестам MySQL на стоковом железе в кластере
Значит такие тесты.
Здравствуйте, Cyberax, Вы писали:
Снова все тот же спор!
Еще лет 5-10 назад рагорались споры и преимуществах и недостатках "толстых" и "тонких" клиентов! И притом еще никто и никогда не смог ответить однозначно! Во всем есть свои плюсы! Притом это вне зависимости от используемых средств! Так как с редства — это средства!!!
1.0 при использовании "толстого" клинета не засоряется база СУБД разного рода зранимками. Существуют только таблицы + минимум логики в программе.
1.1 при использовании тонкого клиента на конечной машине стоит только загрузка данных в какие-то таблицы запуск хранимок. То есть получается, что требования к лиентской машине минимальны. Можно хоть на сотом пне запускать вне хависимости от навороченности логики проекта
1.2 мы не заморачиваемся с контролем версий т.к. каждый клиент запуская программу использует те же хранимки, что и все остальные вне зависимости от даты установки программы
1.3 если вся логика реализована в хранимке и промежуточных таблицах, то происходит немного более быстрая обработка данных т.к., простите, данные немного поближе и никуда их перегонять не надо (тем более по сети). Это довольно заметно на большом кол-ве записей.
1.4 (продолжение 1.1) для обрабтки специализированный сервер с бОльшим запасом резурсов чем у клиента. Итог — меньшая стоимость владения данными для большого кол-ва лиентов. (особоенно актуальна для OLTP-систем)
На мой взгляд, при не чрезмерно большом кол-ве пользователей и их нагрузке на СУБД (OLTP и небольшое кол-во warehouse) наиболее логично использование логики на сервере, чтобы клиент мог только получать и отправлять данные минимально обрабатывая их