Здравствуйте, Sinclair, Вы писали:
V>>Я хорошо знаю базу Northwind потому что, без ложной скромности, являюсь профи по MS Access. )) S>Да я уже понял — ты во всех областях равно подкован.
Это одна и та же область.
Я не раз говорил, что имел дела с VBA в количестве и с самописными ActiveX и COM-объектами на плюсах.
Это всё оно и есть.
MS Access, ИМХО, недооценённая платформа.
Беда того приложения NorthWind, что оно не показывает самые вкусности платформы.
В этой учебной базе можно в любой момент перейти в режим конструктора и "всё испортить".
В MS Access легко отделяется режим разработчика от режима эксплуатации, т.е. когда "эксплуататор" ничего не может менять и ему доступно только разработанное разработчиком меню (в том числе любые контекстные).
К тому же, его как раз было удобно использовать против MS SQL, даже еще до того, как MS SQL был поддержан "официально".
ИМХО, официально они его поддержали не правильно. Еще к MS SQL 6.x я коннектился по ODBC, при этом локальная база представляла из себя кеш.
А движок MS Jet был примечателен тем, что ему можно было пихать объединённые запросы из внешних и "своих" источников данных — это была та самая мегафишка. Есть ли еще на свете такая система, где я одним запросом достаю удалённые данные и делаю им join с некими локальными? ))
И это я уже молчу о том, что контролы MS Access — они все шли как windowless и более эффективного отображения данных в GUI (а тогда и такая эффективность была в цене) я не видел. Любое отображение только виртуальное (этот приём в конкурирующих системах только-только набирал оборот). Писать виртуальные источники данных для отображения в таблицах MS Access — одно удовольствие. Писать windowsless контролы к нему же — аналогично.
Ну и легкая связь с другими док-тами офиса, их элементарное внедрение.
В общем, по тем временам всё остальное выглядело как из 19-го века.
Особенно 1С 6.x (чисто внешне и по гибкости организации офисной работы).
Мощь 1С была в куче готовых типовых операций, соответствующих законодательству, — но это малость другая сторона, чем техническая.
V>>Это не боевая система, в поделках такого уровня десятки таблиц максимум и все твои предыдущие аргументы теряют смысл, если подкреплять их подобными примерами. Тут мне опять не хватает смайлика на сравнимую величину твоей необъективности. S>Угу. На самом деле всё не так, как в реальности. S>Реальные системы, которые я в своей практике наблюдал — этот базы, в которых живут одновременно сотни таких нортвиндов.
ИМХО, это наколенные поделки, разросшиеся до больших масштабов.
Пару раз я и такое видел, и?
Но любые "взрослые базы" сделаны примерно как 1C, R-base, Акцент и прочие промышленного уровня того времени.
Т.е. документы отделены от таблиц движений, отдельно идут регистры, отдельно серии временных данных (типа курсов валют).
Обязательно в явном виде присутствует операция "проводка" (транзакция, фиксирование и т.д.) и обязательно процедура закрытия периода.
Способ хранения исторических и оперативных данных отличается.
Вот как раз по индексам и ограничениям целостности в том числе.
Для read-only можно навертеть индексов сколько душе угодно.
Для оперативно изменяющихся — за это только расстрелять. ))
S>Слабо связанные между собой. Это хорошо видно на диаграммах — там явно видны кластеры вокруг толстых-толстых таблиц с кучей ссылок.
Проблема в другом — во время редактирования строк заказа в Northind, если параллельно брать остатки, то они будут "плавать".
Более того, добавь сюда другой вид документа — нужно переписывать добрую половину базы, чтобы собирать итоги из кучи таблиц-документов.
Детсад, кароч.
Такой херней дельфинисты страдали массово в середине 90-х и мы достаточно наржались в своё время с этой наивности.
Во "взрослой" системе при добавлении нового типа док-та достаточно будет реализовать его связь с таблицей движений и пару операций — проводка документа и отмена. Усё.
V>>А как организованы настоящие боевые системы, где вообще имеет смысл рассуждать о размерности задач, я уже описывал. V>>Мы выше обсуждали таблицу движений, а она связана с таблицей ордеров по одному ровно индексу. S>Очень удобно — вместо разговоров о таблице orders, поговорим о таблице Movements.
Именно так. Удобно.
Потому что тяжеловесное обращение к Orders относительно "однократное" — в момент проводки.
V>>В боевой торговой системе примерно такой набор таблиц: S>1. А как связаны Orders и Documents? Через SourceDocType?
Вот это самый главный вопрос.
Собсно, я затем всё и расписал, бо обнаружил странные (прямо скажем) представления о том, как хранятся данные в промышленных учётных системах.
Через "чистую реляцию" никак не связаны, насколько ты успел понять (надеюсь).
В рамках транзакции меняется состояние док-та из Orders и появляется, либо исчезают строки из Documents и Movements.
Таких Orders в большой системе — многие десятки, а то и больше сотни.
Например: акты возврата от покупателя, акты списания, резервирование от клиента, резервирование от фирмы, переброс товаров в акционные, объединение товаров в новые товары (сборки) или обратно, разбиение товара по "цветам" или обратная "монохромная сборка", ликвидация "цветной" пересортицы — т.д. и т.п., это зависит от конкретной предметной области.
Но таблица движений ТМЦ — одна.
Ну или две в случае оформления приходов и расходов в виде отдельных таблиц.
S>2. Как мы гарантируем, что у Movement и его Document совпадают Subdivision?
Да там не только это надо гарантировать.
Начинать надо с DocumentId.
Твой вопрос более общий: как гарантировать целостность данных в условиях избыточности или отсутствия связей, гарантирующих целостность данных?
Известное решение одно — транзакции.
Моя эволюция:
— сначала расписал на триггерах, где изменения состояния order провоцируют проводку док-та или его отмену с соотв. изменениями таблицы движений и документов. Однажды отчетный период затянулся на 3 месяца и база стала спотыкаться.
— переписал просто на хранимки — это примерно втрое эффективней, чем на триггерах.
— а потом и вовсе отказался от некоторых встроенных ограничений целостности, например от внешнего ключа — еще в 3-5 раз получил прирост.
Далее я сузил многие суррогатные ключи с 32-х до 16-ти бит в сотнях таблиц и неожиданно получил прирост скорости еще вдвое, что аж стало любопытно, бо в 32-х разрядной системе такие вещи не ускоряют, а замедляют. По крайней мере при работе с памятью. Что аж достал по-блату исходники 6-го MS SQL и примерно 3 дня из любопытства разглядывал на длиннющем распечатанном рулоне (матричные принтеры — рулез). ))
Причём, увеличение оперативки сервака такого прироста не дало, дело было в чём-то другом.
После серии экспериментов стало понятно, что физический размер индекса играет рояль.
S>3. Как выглядит код "отгрузки заказа"? Я же правильно понимаю, что мы должны из Order и его OrderDetails породить Document и Movements, одновременно подправив значения остатков в соответствующих Consignments?
Именно так.
S>Обычно как раз тут и начинается эпоха "добавления индексов", потому что наивная версия кода начинает тормозить минутами.
Это стандартный master-slave, как делать для него составной ключ — уже показал.
Заметь, что в таблице движений нет уникального ключа.
Уникальные ключи тоже зло и тормоза, увы.
S>Аналитика нам потребуется позже — и будет интересно, можно ли внедрить её "постепенно", т.е. начав с запросов прямо по исходным данным (а почему нет, пока у нас пара сотен движений в анамнезе)
"Полуаналитика" тоже нужна. Например, у меня была таблица "товары на резерве".
Т.е. вот десятки девочек выписывают накладные, они видят в каждой строке одни и те же остатки.
В наивном виде это будут остатки по факту проводки документов, а для целей выписки нужны остатки с учётом выписываемого за соседним столом в ту же секунду.
S>и потом уже отмасштабировав на ентерпрайз-масштабы.
Подход Northwind не масштабируется от слова никак.
Моя первая система была примерно в таком же виде, потом я устал править сотни запросов при добавлении каждой новой операции и отделил мух от котлет. Мне хватило полугода одновременной эксплуатации и развитием системы (до этого контора выписывала накладные в MS Excel, потом расширилась и перестала справляться).
Потом некоторое время ставил и по другим конторам новое поколение своих поделий (в каждом конкретном случае всё-равно много уникального было), обслуживал их. Ну и насмотрелся на варианты учётных систем, которые заменял своей.
Тогда было их жуткое разнообразие, не то, что сейчас.
А по природе я любопытен, со всеми вытекающими.
В итоге вышло примерно как с той книжкой GoF — ничего нового.
Разве что подсмотрел у 1C прикольный способ хранения временных серий данных — это было их, не побоюсь этого слова, ноу-хау, тут они молодцы.
Остальное — примерно так же или хуже, чем у меня. ))
Например, мой любимый способ представления иерархических данных строг и шустр, хоть и избыточен.
(связь от каждого узла к каждому Parent+расстояние)
Ну и часто наблюдал, что в учётных системах отсутствует возможность накрутить более одной иерархии для тех же данных.
Например, над товарами потенциально можно накрутить несколько слабо пересекающихся иерархий.
Кол-во иерархий зависит от типа товара.
В 1С была всегда одна иерархия, а как клиенты узнавали о такой возможности, то я менее 2-х иерархий не видел.
Три — самое популярное их число.
S>И можно ли это делать инкрементально, без этапа "а щас подождите полгода, пока мы закупаем новое железо и пишем новую систему", потому что "основная" система продолжает развиваться и возможности остановить мир у нас нет.
Так нельзя.
У меня не получилось, только время потратил в кол-ве 2-х месяцев траха.
Потому разделение "исходников" от "движений" — оно фундаметальное.
Оно или есть, или его нет.
За меньшее время я потом с 0-ля сделал систему с таким разделением (и был доволен собою как слон, справедливости ради... да и было мне тогда 26-27).