Представление диапазонов номеров в реляционной базе данных (MySQL) - PullRequest
12 голосов
/ 03 мая 2011

Я пытаюсь понять, существуют ли какие-либо стандартные подходы наилучшей практики для моделирования диапазонов чисел в реляционной базе данных (в данном случае MySQL) и действительно ли это разумная вещь.

Iобъясню задачу, которая поставила вопрос для контекста.

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

Пул потенциальных Идентификаторов имеет диапазон от 0 до примерно 2 ^ 30

Заданному клиенту может быть выделено любое количество Идентификаторов от одного Идентификатора до миллионов в нескольких смежных блоках.

Данный Идентификатор может быть назначен только одному клиенту (т. Е. Это отношение один ко многим)

Очевидно, что будет таблица Customer и таблица идентификаторов, содержащая ключ Customer.

Сложность заключается в том, как смоделировать Идентификаторы:

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

Второй (и я думаю, более перспективный) вариант заключается в том, чтобы строка представляла диапазон значений с минимальным и максимальным значением.Это сделало бы запросы немного более сложными (я предполагаю, что запрос для проверки, использовался ли идентификатор, будет запрашивать диапазоны с «Минимум ниже X» и «Максимум выше X»), но приведет кменьше строк и, вероятно, будет проще управлять и обновлять.

Я бы приветствовал любые мнения о том, является ли это хорошим подходом, а если нет, то если есть очевидный лучший подход, который мне не хватает.

Ответы [ 5 ]

7 голосов
/ 03 мая 2011

Если диапазоны не пересекаются, вы можете сохранить их как пары значений INT:

CREATE TABLE customer_range
        (
        customerId INT,
        rgStart INT,
        rgEnd INT,
        PRIMARY KEY (customerId, rgStart),
        UNIQUE KEY (rgStart)
        )

Чтобы запросить клиента, которому принадлежит номер, используйте это:

SELECT  customerId
FROM    customer_range
WHERE   rgStart <= $mynum
        AND rgEnd >= $mynum
ORDER BY
        rgStart DESC
LIMIT 1
2 голосов
/ 02 апреля 2013

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

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

https://wiki.postgresql.org/images/7/73/Range-types-pgopen-2012.pdf

С наилучшими пожеланиями,

Ник

1 голос
/ 03 мая 2011

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

Я бы еще поработал над фактическими запросами, которые вы, вероятно, захотите выполнить, и разработал бы решение на этой основе.Например, вы хотите перечислить все идентификаторы, которые принадлежат одному клиенту?Вы хотите проверить, у какого клиента есть несколько идентификаторов?Хотите узнать, сколько идентификаторов принадлежит клиенту?Последнее немного сложнее, если у вас есть таблицы «диапазона» - вместо того, чтобы делать "select count(*) from ranges where customer = 1", вам нужно будет рассчитать количество IP-адресов в каждом диапазоне для клиента и сложить их.Не ракетостроение, но может быть медленнее в реальном мире ...

0 голосов
/ 03 октября 2016

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

0 голосов
/ 03 мая 2011

Если вы сделаете такой стол

идентификаторы таблиц

id_start not null unsigned integer /*not autoincrement!*/
id_end not null unsigned integer 
customer_id unsigned integer not null
foreign key FK_customer (customer_id) REFERENCES customer.id
primary key (id_start, id_end)
key id_end (id_end)

Теперь вы можете просто проверить бесплатный ключ, выполнив

SELECT count(*) as occupied FROM ids
WHERE 100 between id_start and id_end;

Чтобы проверить свободный диапазон, сделайте

SELECT count(*) as occupied FROM ids
WHERE NOT ('$low' > id_end) AND NOT ('$high' < id_start)
...