Postgres индексы для внутреннего соединения с предложением where в обеих таблицах - PullRequest
1 голос
/ 19 июня 2020

Мы используем Postgres для модели разрешений RBA C с группами и пытаемся подумать о лучших необходимых индексах, предполагая, что наша БД имеет следующую схему:

Таблица субъектов

id, external_type, external_id, group_id

Таблица ресурсов

id, group_id, external_type, external_id, role_id

Обе таблицы предназначены для ответа на один вопрос:

Можно тема [S] выполнить действие [A] на ресурсе [R]

Итак, нам нужно получить все роли, которые пользователь имеет на ресурс, из всех групп разрешений, в которых он участвует.

  • A субъект может иметь K строк в таблице субъектов, по одной для каждой группы, членом которой он является.
  • Ресурс может иметь M строк в таблице ресурсов, по одной для каждой группы, для которой этому ресурсу была назначена роль.
  • Мы решили денормализовать ресурсы, группы и роли в одна таблица для оптимизации чтения.
  • Мы решили не денормализовать предметы в той же таблице - чтобы избежать u pdating много записей при каждом изменении структуры группы.
  • И K, и M могут быть очень большими - пользователь может быть во многих группах, а ресурс может принадлежать многим группам.

Таким образом, запрос будет:

SELECT role_id
FROM resources
INNER JOIN subjects
ON resources.group_id=subjects.group_id
WHERE subjects.external_type="user" AND subjects.external_id=123
  AND resources.external_type="order" AND resources.external_id=456

Мы решили определить следующие индексы:

Subjects: <external_type, external_id>, <group_id>
Resources: <external_type, external_id>, <group_id>

Может кто-нибудь, пожалуйста, объясните, как внутреннее соединение с предложением where относится к 2 таблицам. индексы? Выполняются ли они параллельно, а затем соединяются оператором ON, или только индексы одной таблицы будут использоваться для where, а затем подключены с помощью соединения ON?

Следует ли использовать разные составные индексы? как-то добавить group_id к составным индексам?

Любая ссылка на аналогичный вариант использования или выбор индексов для сложных JOIN запросов будут полезны.

1 Ответ

1 голос
/ 19 июня 2020

Это можно сделать разными способами. Он мог независимо читать как индексы, так и таблицы, а затем sh объединить или объединить их вместе. Или он мог игнорировать один или оба индекса, вместо этого выполняя последовательное сканирование таблиц, если считал, что это будет быстрее (потому что индексы вернут большую часть строк). Или он может сделать вложенный l oop, где он использует константы из предложения WHERE плюс изменяющийся group_id из предложения ON, чтобы сформировать тройку, которую он будет искать в индексе трех столбцов для одной из таблиц (внутренняя таблица ). Внешняя таблица также может управляться ее индексом (с использованием только первых двух столбцов, которые являются постоянными на протяжении всего запроса) или с помощью последовательного сканирования.

Если вы хотите знать, какой план используется , выполните EXPLAIN или лучше EXPLAIN (ANALYZE, BUFFERS) запроса.

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