база данных с двумя столбцами логическая ИЛИ индексируемая, или создайте отдельную таблицу "index"

StackOverflow https://stackoverflow.com//questions/11712344

Вопрос

У меня есть следующая таблица:

Matches -> match_id, team_a_id , team_b_id, score

В этой таблице будут записаны матчи между двумя командами (команда А и команда В).Однако иногда команда А играет в качестве принимающей стороны, а иногда команда В играет в качестве принимающей стороны.Поэтому, когда я попытался найти историю совпадений между командами a и b.То, что я в настоящее время делаю, это

select * from matches where (team_a_id = 1 and team_b_id = 2) or (team_a_id = 2 and team_b_id = 1);

Есть ли какой-нибудь лучший подход к такому случаю?Что касается приведенного выше запроса, правильно ли я включаю индекс комбинации team_a_id и team_b_id?Но даже в этом случае у меня все еще есть Логическое условие OR между AB ИЛИ BA.

В качестве альтернативы, У меня есть еще одна идея, которая заключается в том, чтобы иметь другую таблицу, скажем, history

History -> team_hash, match_id

Я вручную создаю team_hash, где hash(a,b) == hash(b,a).Но это приводит к немного более медленной вставке, но более быстрому чтению.Или это действительно более быстрое чтение?

Это было полезно?

Решение

Предполагая, что существует составной индекс на {team_a_id, team_b_id}, СУБД может выполнить вашу инструкцию SQL, используя только два поиска по индексу (один для team_a_id = 1 and team_b_id = 2 а другой для team_a_id = 2 and team_b_id = 1), что происходит очень быстро.Я не ожидаю, что вы сочтете эту работу недостаточной.


Однако есть способ устранить один из этих запросов по индексу.Добавьте ограничение...

CHECK(team_a_id < team_b_id)

... и кодировать "направление" (т.е.какая команда является принимающей) в отдельном поле, если необходимо.Таким образом, ты знаешь team_a_id = 2 and team_b_id = 1 это никогда не может быть правдой, поэтому вам нужно только искать на team_a_id = 1 and team_b_id = 2.


"Симметричное" хеширование - отличная идея, но:

  • Корректность хэша не может быть обеспечена декларативно - вам нужно будет сделать это через триггер или на уровне приложения.
  • Это избыточные данные.Вам нужно будет сохранить team_a_id и team_b_id в любом случае, для разрешения конфликтов хеширования.Увеличение объема данных фактически означает уменьшение объема кэша.
  • Это может фактически увеличить количество индексов - для эффективного обеспечения ссылочной целостности, вероятно, потребуются индексы на team_a_id и team_b_id даже если они вам не нужны для фактического SQL-запроса.В дополнение к увеличению нагрузки на кэш, необходимо поддерживать каждый дополнительный индекс, что потенциально снижает производительность ВСТАВКИ / ОБНОВЛЕНИЯ / УДАЛЕНИЯ.Ситуация особенно серьезна в InooDB, где вы не можете отключить кластеризацию, поэтому вторичные индексы, как правило, стоят дороже, чем в таблицах на основе кучи (см. "Недостатки кластеризации" в эта статья).

Другие советы

Вы также можете сделать вашу точку зрения что-то вроде этого

((team_a_id = 1 and team_b_id = 2) or (team_a_id = 2 and team_b_id = 1))
AND team_a_id IN (1,2) AND team_b_id IN (1,2)
.

Таким образом, можно будет использовать индекс, как (Team_a_id, team_b_id).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top