база данных с двумя столбцами логическая ИЛИ индексируемая, или создайте отдельную таблицу "index"
-
13-12-2019 - |
Вопрос
У меня есть следующая таблица:
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).