Comments 22
Как по мне, это просто синтаксический сахар. Мне ближе вариант с тремя таблицами в MySQL.
По сравнению с вариантом 3 таблиц не только. Тут есть контроль целостности, а так же богатый список операторов на пересечения, свободность и прочее. На КСВ может это не так очевидно. Система бронирования в отелях может быть более показательна, но я хотел делать слишком сложный пример.
Вы заблуждаетесь. Если БД не поддерживает диапазоны, то она так же ничего не знает о том, могут ли они пересекаться. Поэтому в плане запроса будут сканироваться все начала диапазонов меньшие и равные искомому значению или все концы диапазона большие или равные искомому значения, в зависимости от их очередности в индексе. А в случае GIST БД по индексу сразу находит нужную запись.
Последний вариант с постгресом всё-равно требует нормализации.
А так да, постгрес хорош.
Нормализации с разнесением по 3 таблицам? С ходу в голову приходит только такой вариант.
Если использовать не два int4range, а box type - получится нормализация )
А можно немного идею раскрыть? Какая схема БД при этом получается?
Вместо двух полей age и experience будет одно поле age_and_experience box
X координата возраст, а Y - стаж. И ищем прямоугольник, внутри которого требуемая координата, используя GIST индекс.
Оччень интересный вариант. Т.е. у нас будет 2ое поле в котором прямоугольники не могут пересекаться и даже соприкасаться. Т.е. у нас все сведется к 2 полям в таблице: age_and_experience box и value number. Обязательно попробую и этот вариант. Спасибо за идею!
В общем я сделал вариант и с box. К сожалению в настоящее время Хабр пока не дает отредактировать статью и добавить туда этот вариант. Но данная заметка есть в формате видео. Если интересно, оно публичное. Ссылка на схему D: https://www.youtube.com/watch?v=LOtEC68d1Aw&t=725s
Зря не упомянули в видео причину, почему я предложил вариант с box. Она в комментарии ниже:
"в целях обучения, промолчать о варианте с box я просто не смог. Все же
поддержка геометрических типов данных и их индексации - одна из сильных
сторон PostgreSQL"
Так-то да, но может выстрелить нечаяно =)
Как видим, в этом случае получается 50 записей (их можно сократить до 20, предлагаю подумать и написать в комментариях как это сделать).
Думаю для возраста 16-21 и стажа 0,1,2 коэффициент одинаковый, и их можно объединить в 1 запись. И тогда получится 20 записей.
При варианте с 3 таблицами, похоже никто не мешает вставить повторяющиеся диапазоны и в таблицу возраста и в опыта. Контроля уникальности нет. Тогда этот вариант можно заменить 1 таблицей: id, age_from, age_to, experience_from, experience_to, coefficient.
Думаю для возраста 16-21 и стажа 0,1,2 коэффициент одинаковый, и их можно объединить в 1 запись. И тогда получится 20 записей.
Это решение очевидно, думаю, автор имел в виду именно его. Более того, если прибегнуть к экстремальному сжатию диапазонов, то количество записей можно уменьшить до 16.
Но вот правильность такого "сжатия" - крайне сомнительна. Если в следующем году большие дяди решат, что для какой-то ячейки исходной таблицы надо подвинуть коэффициент на сотку, то внесение корректировки потребует минимум двух действий вместо одного (в обоих вариантах реализации), с количеством корректируемых записей от 2 до 5 в зависимости от использованного сжатия.
К тому же при таком сжатии сложнее хранить историю, вернее, работать с прошлыми периодами...
Предложенный вариант с 1 таблицей тоже не помешает вставить повторяющиеся диапазоны, т.к. на уровне РСУБД это будут int + уникальный индекс. Но он позволит создать диапазон 22-22 при существовании диапазона 16-24.
В этом и суть отдельного типа данных range. Кроме цифр (границ диапазона) PostgreSQL еще и знает, что это диапазоны и может контролировать консистентность данных из коробки. Плюс он дает над ними еще и арифметику (которая будет полезна при составлении расписаний).
Хочу добавить, что время индексации GIST заметно превышает время индексации BTREE. Поэтому, для таблиц с большими объемами вставок или модификаций ключевых значений, GIST может суммарно проиграть по производительности.
Продолжение истории с 4 вариантом - box, читайте в этой заметке: Сохраняем диапазон в виде box типа
PostgreSQL: пример использования диапазонного типа данных при расчете коэффициента возраст-стаж в ОСАГО