У меня есть две таблицы в базе данных Postgres 11:
client table
--------
client_id integer
client_name character_varying
file table
--------
file_id integer
client_id integer
file_name character_varying
Таблица клиента не разделена, таблица файлов разделена по client_id (разделение по списку).Когда новый клиент вставляется в клиентскую таблицу, триггер создает новый раздел для файловой таблицы.Таблица файлов имеет ограничение внешнего ключа, ссылающееся на таблицу клиента по client_id.
Когда я выполняю этот SQL (где c.client_id = 1), все выглядит нормально:
explain
select *
from client c
join file f using (client_id)
where c.client_id = 1;
Сокращение разделаиспользуется, сканируется только раздел file_p1:
Nested Loop (cost=0.00..3685.05 rows=100001 width=82)
-> Seq Scan on client c (cost=0.00..1.02 rows=1 width=29)
Filter: (client_id = 1)
-> Append (cost=0.00..2684.02 rows=100001 width=57)
-> Seq Scan on file_p1 f (cost=0.00..2184.01 rows=100001 width=57)
Filter: (client_id = 1)
Но когда я использую предложение where, например "where c.client_name = 'test'", база данных сканирует все разделы и не распознает, чтоclient_name "test" равно client_id 1:
explain
select *
from client c
join file f using (client_id)
where c.client_name = 'test';
План выполнения:
Hash Join (cost=1.04..6507.57 rows=100001 width=82)
Hash Cond: (f.client_id = c.client_id)
-> Append (cost=0.00..4869.02 rows=200002 width=57)
-> Seq Scan on file_p1 f (cost=0.00..1934.01 rows=100001 width=57)
-> Seq Scan on file_p4 f_1 (cost=0.00..1934.00 rows=100000 width=57)
-> Seq Scan on file_pdefault f_2 (cost=0.00..1.00 rows=1 width=556)
-> Hash (cost=1.02..1.02 rows=1 width=29)
-> Seq Scan on client c (cost=0.00..1.02 rows=1 width=29)
Filter: ((name)::text = 'test'::text)
Так что для этого SQL сканируются все разделы в таблице файлов.
Так должен ли каждый выбор использовать столбец, на который разбиты таблицы?Разве база данных не может отклоняться от критериев сокращения раздела?
Редактировать: Чтобы добавить некоторую информацию:
В прошлом я работал с Oracleбазы данных большую часть времени.
План выполнения будет выглядеть примерно так:
- Выполните полное сканирование таблицы на клиентской таблице с именем клиента, чтобы узнать client_id.
- Сделайте «PARTITION LIST» доступ к таблице файлов, где разработчик SQL заявляет PARTITION_START = KEY и PARTITION_STOP = KEY, чтобы указать, что точный раздел неизвестен при расчете плана выполнения, но доступ будет сделан только к спискуразделов, которые рассчитываются по client_id, найденному в таблице client.
Это то, что я ожидал и в Postgresql.