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

Мои пожелания к СУБД будущего, а также к Росреестру в части транзакционности

Время на прочтение4 мин
Количество просмотров3.1K
Всего голосов 23: ↑9 и ↓14-5
Комментарии37

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

1. Edition-based redefinition
2. TO_CHAR(SYSDATE,'MONTH','NLS_LANGUAGE=RUSSIAN')
3. Начиная с 11g точно есть, раньше – лень смотреть
4. Такое поведение по умолчанию некорректно, но если очень надо, можно за полчаса написать скрипт, выдающий соответствующие полномочия, с использованием USER-DEPENDENCIES
>> 2. TO_CHAR(SYSDATE,'MONTH','NLS_LANGUAGE=RUSSIAN')

Иногда нужен не именительный падеж. «Второго апреля», «Восьмого марта».

>> 3. Начиная с 11g точно есть, раньше – лень смотреть

Returning без into? Просто выдающий данные, как это делает Select? Можно пример?
У нас в текущей системе как раз 11g.
2. Вот тут непонятно, какой вопрос к разработчикам СУБД. Не так много языков, где есть понятие «падежа», и не во всех языках с падежами изменяется само слово

3. returning без into – очень странный запрос. Но если есть суровая революционная необходимость, то копайте в сторону ref_cursor или pipelined functions
2. Так это всё равно все фирмы делают, но во всех проектах по-разному. Почему не встроить в БД? В одном городе снесли все ограды и дорожки, а затем по протоптанным людьми тропинкам положили новые. Вот, если все люди топают по одной и той же тропинке, почему её не проложить как надо, организованно и стандартно?

3. Не думаю, что создать запись и в той же команде узнать её id (создаваемый автоинкрементно, в случае оракла через сиквенс) это странный запрос. Это самый распространённый запрос. Который хочется написать в PL/SQL Developer в одну строку, без создания переменной, вывода её значения и прочих шаманских танцев.
2. Потому что это не относится к СУБД. Управление НСИ – это совершенно отдельная область знаний.

3. Автоинкремент – это плохой шаблон, триггер – тоже плохой шаблон. Так писали 20 лет назад, а сейчас так писать не надо. Гораздо лучше взять из базы значение последовательности, а идентификатор новой записи вычислять как S*1000+i, где i – номер вставляемой записи. Как тысячу записей вставили – взяли новый элемент последовательности.
>> Гораздо лучше взять из базы значение последовательности, а идентификатор новой записи вычислять как S*1000+i, где i – номер вставляемой записи. Как тысячу записей вставили – взяли новый элемент последовательности.

Если так сделать, order by id не будет обеспечивать исторический порядок вставок в таблицу. Плюс проблемы со скоростью из-за дырок. Придётся делать order by datetime_creation, каковое поле может отсутствовать, это более ресурсоёмко, плюс учитывайте что время на компьютере меняется квантами (в винде в зависимости от настройки это от 10 до 55 милисекунд) то есть близкие по времени записи будут не в том порядке.
Использование первичного ключа для чего-то кроме первичного ключа – это тоже очень плохой шаблон. Судя по вашему описанию, там вся система – костыль на велосипеде копипейстом погоняет, а требования – к СУБД будущего…
Я вам назвал 4 причины, вы вместо того чтобы ответить продолжаете навешивать ярлыки. Вы институтский преподаватель?

Имеющий дыры — промежутки праймари кей работает медленнее — это из практики, не теории. Что вы выигрываете своим методом? Скорость добавления в базу? Для закачки больших массивов данных используют BCP.
Вообще-то тему «будущего» вы сами подняли в заголовке. СУБД будущего ориентируются всё-таки на современные подходы к разработке, а не на поддержку дремучего legacy. Как по мне, так будущее за KV-хранилищами (потому что при использовании JPA навороченный SQL не очень-то нужен) и умными сетевыми СХД (типа Amazon Aurora).

Своим методом я выигрываю уменьшение конкуренции за последовательность. Это не магический объект, а просто строка в системной таблице, обёрнутая «синтаксическим сахаром».

А вот мне даже любопытно, какая операция выполняется медленнее, если в PK есть промежутки? У меня фантазии не хватает.
Селекты, конечно. по id = ..., по id in(...,...,...), по id between.
Я не знаю точно, почему так.
Фундаментальных причин для этого нет. Ответ на вопрос «почему так» надо искать в условиях тестирования:

  • насколько прогрет кэш в первом и втором случае
  • какие диапазоны идентификаторов (работа с длинными идентификаторами может быть чуть медленнее, чем с короткими, но заметно это на сценариях типа NUMBER vs VARCHAR2)
  • какие параметры PCTFREE/PCTUSED у индекса и у таблицы
  • сколько записей в таблицах
  • не было ли массовых удалений из таблицы

Ну и так далее.
order by id не будет обеспечивать исторический порядок вставок в таблицу.

Вам правильно говорят, что у id не должно быть отношения порядка.
Да, придется делать поле datetime_creation, если вам нужно по нему выбирать.


С какой целью вам вообще нужно выбирать по дате вставки?

Чтобы договор номер 2 не создавался раньше договора номер 1?
Чтобы логировать и показывать события в правильной последовательности?
Чтобы 18 марта 2019 года фирма заключала договора от 20115 до 20267, а не перечислять их номера через запятые?

Поле datetime_creation всё равно делать, чтобы помнить дату и время. Но это не гарантирует правильный порядок, как я показал выше.
Чтобы договор номер 2 не создавался раньше договора номер 1?

Это какие-то особенные договора? Может быть надо более явно отразить эту логику в коде и требованиях? Предположу, что договор 1 например о покупке товара, а договор 2 о продаже товара. Может их надо связать с какой-то сущностью "сделки"?
Может сделать в договоре 2 сделать ссылку на договор 1? Что-то в духе "на основании такого то".


Показывать события в нужной последовательности можно и с помощью datetime_creation.


Выборку договоров за 18 марта 2019 года можно тоже сделать по полю datetime_creation.


Кстати, а как вы без даты создания узнаете что диапазон договоров за эту дату начинается именно с 20115 и заканчивается на 20267?

Кстати, а как вы без даты создания узнаете что диапазон договоров за эту дату начинается именно с 20115 и заканчивается на 20267?
Никак. Но мне не придётся передавать в функцию список id. Я передам два числа, от и до.
Показывать события в нужной последовательности можно и с помощью datetime_creation.
сказано выше:
время на компьютере меняется квантами (в винде в зависимости от настройки это от 10 до 55 милисекунд) то есть близкие по времени записи будут не в том порядке.
Например, менеджер заполнил форму о заключённых 5 договорах и нажал ОК. В системе они появились одновременно, но с порядком следования. Порядок следования будет потерян.
Но мне не придётся передавать в функцию список id. Я передам два числа, от и до.

Почему это лучше, чем передавать две даты?


Например, менеджер заполнил форму о заключённых 5 договорах и нажал ОК. В системе они появились одновременно, но с порядком следования. Порядок следования будет потерян.

Тут вопросы уже к заполняющей системе. Почему эти договоры заключаются одновременно, а не последовательно?
Что если в одном из договоров ошибка, а в других все нормально?

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

Про даты: а если той же функцией надо обработать 1 договор?

>> Что если в одном из договоров ошибка, а в других все нормально?

Это не повод для delete. В серьёзных системах никогда ничего не delete. Выставляют состояние — ошибка, удалён, клиент передумал, менеджер выдумал договор который не заключался, и всё такое.
а если той же функцией надо обработать 1 договор?

Я так понимаю, вы делаете одно и то же действие как над пачкой договоров, так и над одним.
Значит у вас будет функция обработки одного договора, которая принимает один id и другая функция, которая принимает диапазон дат и вызывает первую функцию.


Предполагаю, что следующее возражение будет о том, что у вас там глобальные переменные меняются и side-эффекты есть. Я угадал?

Представьте что функция упаковывает переданные в неё договора в email письмо и отсылает директору. Зачем ему 250 писем вместо одного письма? Если он попросил один договор прислать, то ему пришлют. При чём тут глобальные переменные…

Значит все таки side-эффекты.
Это все у вас в СУБД делается что ли?


Ну тогда три функции. Одна с фильтром по диапазону дат, другая с указанием конкретного договора. Обе вызывают третью, в которой уже отправка емейла.


Это ведь наверняка два разных сценария использования. Там точно нужен один и тот же емейл?
Может быть при отправка одного договора "на посмотреть", его надо как-то иначе оформить?

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

Вы тоже. Это решается иначе.

Как?

Самое простое — Назначать клиенту с названием «ООО Рога и Копыта» буквенный номер договора, образованный транслитом по первым 5 согласным названия: Договор RgKpt-0001, договор RgKpt-0015…
Сокращение хранить в базе как атрибут клиента, который редактируется вручную и должен быть уникальным.

А там, по задаче. Если не всегда есть интернет — формировать UID, если делать примитивно — то xor 1234567, и так далее по обстоятельствам.

Если надо показать себя крутым — то *1000+rand(1000) :)

Ну то есть вы сделаете другое поле, которое будет служить суррогатным ключом, а id будете держать чтобы помнить очередность заключения договоров?
Не проще ли сокращение сделать первичным ключом, а очередность помнить по дате?


атрибут клиента, который редактируется вручную

Вот это тоже непонятно. Зачем нам его редактировать?
Ну то есть вы его распечатали на какой-то официальной бумажке с печатями и подписями, а потом менеджер может просто взять и изменить идентификатор в базе и концы в воду.

ОК, редактируется вручную при первом вводе клиента, далее не редактируется. Всё равно договор привязан к клиенту не по RgKpt а по id. Да, при такой конфигурации в таблице два уникальных поля. Но вы же не будете ссылаться на эту таблицу из других таблиц через поле-текст?
Но вы же не будете ссылаться на эту таблицу из других таблиц через поле-текст?

Ну тут два варианта.


  1. Либо вы поддерживаете два уникальных поля, одно из которых нужно для определения порядка, потому что в системе могут заноситься несколько договоров одновременно.
  2. Либо вы используете один единственный id в целях уникальной идентификации и сокрытия бизнес-информации, а дату — для определения порядка заключения.

Вы серьезно думаете, что экономя на джойне по строковому id вы что-то выигрываете в первом варианте?

Обычно есть «номер договора» — который печатают в документах и в нём могут быть буквы, и id договора — целочисленное поле. Оба поля уникальны в таблице договоров (либо поле номер не уникально, если в таблице хранятся и те договора, номер которых формирует контрагент — тогда есть шанс что два разных контрагента одинаково назовут договор с вами). Это более-менее стандарт…

Дату нельзя использовать для определения порядка следования, я дважды написал, почему.

Если менеджер носит свой ноутбук и заключает договора в тех местах где не всегда ловит интернет, добавьте UID.
Так это всё равно все фирмы делают, но во всех проектах по-разному.

Не все и "по разному" тоже не просто так взялось. Почему вам нужна именно таблица для падежей месяцев? Почему не функция с case when then… end?

Идеально было бы передать в Росреестр на выполнение следующий скрипт:
А причем, я извиняюсь, тут РР?! РР фиксирует результаты в виде записей КУ и ГРП. Если вы каким-то образом сумеете провернуть такую сделку — результаты её РР зарегистрирует. Имхо, тут вопрос не столько «транзакционности» — которую, кстати, РР вполне даже поддерживает, как минимум, в плане ГРП — сколько фондирования такой сделки.

Кроме этого, Росреестр не поддерживает обременение строящегося по ДДУ жилья, а мог бы, это элементарное действие в отношении простого фьючерса.
?! Каким образом вы представляете себе обременение права, которого (пока ещё) нет? Можно даже «на пальцах». ДДУ — сам по себе уже эдакий «фьючерс права». И начинать надо, наверное, не с РР, а с наличия отсутствия КФО, готовых участвовать в таком — скажем так — деле :-)

На всякий случай, если я вас не так понял. Если же речь об обременении самого ДДУ — то РР это вполне себе поддерживает.
Речь об обременении самого ДДУ. Значит, у меня старые сведения.
А причем, я извиняюсь, тут РР?! РР фиксирует результаты в виде записей КУ и ГРП.
Вот именно. По одной и раздельно. А у меня в примере — транзакция, с вложенной транзакцией внутри неё, и блоком TRY-EXCEPT. И этого он не может. И я описал негативные последствия.
Что «вот именно»?! РР — внезапно — не проводит *сделки*. Сделки проводят субъекты. Сами ли, с участием ли третьих сторон — не суть важно. Важно то, что РР лишь фиксирует *результат* этих сделок. Т.е. хотеть от РР всякого типа: «Деньги X отдать Y» и «ЕСЛИ_ОШИБКА» — по меньшей странно. Этих вещей с точки зрения КУ/ГРП (область деятельности РР) просто не существует.

Если уж и «хотеть» такого рода «транзакционность», то надо хотеть это на той стороне, что проводит сделки… вводить какого-либо рода «гаранта», в лице банка, или чего-то типа «дом.рф» и уже там, «наворачивать» с «Деньги X передать Y» и прочими «ЕСЛИ_ОШИБКА».

А РР и пять лет назад (точно, даже 7… может и раньше) мог обрабатывать обращение, в котором несколько связанных заявлений (в вашем случае — их будет три) о «переходе права».
Связанных транзакцией? Это означает, что если хоть одна из трёх операций не выполнится, то не выполнится никакая?

Ну, не знаю… Начнём с того, что Росреестр не ведёт приём граждан. Приём граждан ведёт МФЦ. Я пытался через МФЦ подать одновременно две операции — снять обременение и зарегистрировать куплю-продажу, мне отказали. Сказали, что сначала требуется выполнить одно, а затем другое.
Правильно Вам ответили. Как вы себе представляете параллельное выполнение этих операций?
Сначала снимается обременение и только потом появляется возможность проводить сделки с объектом недвижимости. И не забывайте о Регламенте работы РР. Ваши заявления обрабатываются не 1сек, а несколько дней-недель, а то и месяцев.
Транзакция не означает что операции в ней выполняются параллельно. (Тем более что данный случай это и не транзакция.) Зачем я должен дожидаться пока снятие обременения дойдёт обратно до МФЦ, я его получу, и только потом смогу совершить сделку купли продажи, потратив ещё время на передачу из МФЦ в РосРеестр нового запроса?

Когда Delphi программа посылает на сервер две команды, не обязательно связанные транзакцией, это всё равно лучше делать одним запросом, чтобы не удвоить издержки на обмен данными.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации