Проектирование базы данных для сохранения и запроса динамического диапазона? - PullRequest
0 голосов
/ 17 февраля 2019

Мне нужно спроектировать таблицу базы данных (postgres), которая может сохранять динамический диапазон чего-либо.

Пример: у нас есть таблица курса.Каждый курс может иметь (минимум И максимум) ИЛИ (определенное количество) участников.Математический курс может быть начат с 4-10 студентами, в то время как на курсе физики должно быть ровно 8 студентов.

После этого я хочу иметь возможность запросить это.Допустим, я хочу все курсы, которые могут принять 6 студентов.Курс по математике должен быть возвращен, курс по физике - нет, так как для него требуется ровно 8 студентов.

Когда я запрашиваю 8 студентов, оба курса должны быть возвращены.


Для реализации я подумал о двух простых полях: min_students и max_students.Тогда я мог бы просто проверить, равно или нет число между этими числами.

Проблема в том, что я должен заполнять оба столбца каждый раз.Также для курса физики, который требует ровно 8 студентов.

пример:

name    | min_students | max_students 
--------|--------------|-------------
math    |            4 |           10
physics |            8 |            8

Есть ли более элегантный / эффективный способ?Я также подумал о том, чтобы сделать столбец max_students обнуляемым, чтобы можно было проверить min_students = X OR (min_students >= X AND max_students <= Y)

Будет ли это более эффективным?А как насчет производительности?

1 Ответ

0 голосов
/ 18 февраля 2019

Каждый курс может иметь (минимум И максимум) ИЛИ (определенное количество) участников.

Все курсы имеют минимум и максимум, для некоторых курсов это бывает одинаковое значение.Это может показаться тривиальным, но если подумать об этом, то вы сможете определить проблему проще.

Вместо:

min_students == X OR (min_students >= X AND max_students <= Y)

вы можете выразить это как:

num_students BETWEEN min_students AND max_students  

BETWEEN включительно, поэтому 8 BETWEEN 8 and 8 верно

Относительно оптимизаций

Дополнительные условия усложняют экспоненциально сложные запросы для людей, что приводит к пропущенным граничным случаям и обычно в любом случае приводит к неэффективным запросам.Сосредоточьтесь на том, чтобы сделать код легким для понимания или «элегантным», и никогда не жертвуйте удобочитаемостью для производительности, если вы не действительно уверены, что у вас есть проблема с производительностью, и ваша оптимизация действительно помогает.

Если у вас есть таблица с 10-миллионными строками, возможно, стоит обратить внимание на супероптимизацию использования диска, если вы работаете на крайне ограниченном hw, но сокращение использования диска таблицей даже с 20 МБ почти наверняка тратит время в любомнормальные обстоятельства, даже если это не делает код более сложным.

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

Альтернативное решение

При использовании типа данных диапазона сравнение будет выглядеть следующим образом:

num_students @> x

, где num_students представляет диапазон (например, от 4 до 10)и @> означает «содержит значение»

create table num_sequence (num int);
create table courses_range (name text, num_students int4range);

insert into num_sequence select generate_series(3,10);
insert into courses_range values 
  ('math', '[4,4]'), ('physics', '[6,7]'), ('dance', '[7,9]');

select * from num_sequence 
left join courses_range on num_students @> num;


 num |  name   | num_students 
-----+---------+--------------
   3 |         | 
   4 | math    | [4,5)
   5 |         | 
   6 | physics | [6,8)
   7 | physics | [6,8)
   7 | dance   | [7,10)
   8 | dance   | [7,10)
   9 | dance   | [7,10)
  10 |         | 

Обратите внимание, что диапазоны выводятся в формате, аналогичном [x, y), жесткие скобки означают «включительно», а круглые скобки означают «исключение» и то, что для целых чисел: [4,4] = [4,5) = (3,5)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...