MySQL эффективно хранит неориентированные ребра графа

Я хочу сохранить неориентированные ребра графика (например, для друзей). Для хранения и извлечения всех друзей узле a, можно использовать:

создайте две строки на ребро, запрос на один столбец на узел:

+--------------------------+
| id | from_node | to_node |
+--------------------------+
| 1  |  a        |  b      |
| 2  |  b        |  a      |
+--------------------------+
SELECT * FROM `x` WHERE from_node = a

создайте одну строку на ребро, используйте OR:

+--------------------------+
| id | node_a    | node_b  |
+--------------------------+
| 1  |  a        |  b      |
+--------------------------+
SELECT * FROM `y` WHERE node_a = a OR node_b = a

что делает поиск более эффективным?

  • стол x С 2n строк, индексы на from_node и to_node поиск по одному колонка
  • стол y С n строк, индексы на node_a и node_b поиск по обоим столбцам с помощью OR

2 ответов


Если вы оптимизируете все, то X будет самым быстрым, предполагая, что Вы читаете данные с диска и запрашиваете друзей одного человека. это потому, что вы можете расположить свои данные на диске так, чтобы они соответствовали одному индексу, который вы запрашиваете. таким образом, для одного человека вам нужно всего лишь сделать один поиск диска. Y требует запросов по двум индексам, поэтому может означать несколько попыток получить друзей, даже для одного человека (а время доступа к диску обычно доминирует просто запросит.)

посмотреть кластеризованных индексов в Википедии (а руководство mysql)

Если вам посчастливилось узнать, что данные всегда будут в памяти, то они, скорее всего, будут "достаточно быстрыми" (и даже если данные находятся на диске, они могут быть достаточно быстрыми - я не говорю, что X-лучший дизайн, только то, что его можно сделать наиболее эффективным).


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

Я храню неориентированные графики, такие как ваш второй пример, и имею ограничение, что node_a должен быть меньше node_b. Затем вы тривиально размещаете a UNIQUE ограничение на пару и знать, что данные согласованы. Запросы должны немного больше работать, сравнивая node_a с меньшим из {a, b} и node_b другого значения. PostgreSQL (БД, которую я знаю лучше всего) предоставляет GREATEST() и LEAST() функции, которые помогают здесь.