Совет по созданию объединенного представления двух сторонних таблиц с перекрывающимися строками. - PullRequest
0 голосов
/ 21 января 2020

Цель: создать отчетный Postgres экземпляр для конечного количества других postgres экземпляров. Все экземпляры имеют таблицу структуры каталогов и таблицу томов. Проблема в том, что таблица томов для всех начинается с индекса 1 для первого тома (автоинкремент). Все удаленные таблицы (использующие FDW) являются правильными индексами для быстрого поиска по volume_id. Итак, каков наилучший способ создать представление, которое включает в себя внешние таблицы, которые позволяют запрашивать, где volume_id может быть одинаковым, но имя тома может быть совершенно другим. Один из возможных ответов - создать смещение на лету, но это выглядит медленно

Упрощенная схема для таблицы томов:

 id bigint
 name text

Упрощенная схема для таблицы каталогов:

 id bigint
 path text
 volume_id bigint
 parent bigint
 name text

чтобы получить все тома для тома Foo:

select d.* from directories d INNER JOIN volumes v on v.id = d.volume_id WHERE v.name = 'Foo';

представлений для объединения внешних каталогов:

create view volumes AS (select * from f1_volumes UNION SELECT id + 10000, name FROM f2_volumes);

create view directories AS (select * from f1_directories UNION SELECT id, path, volume_id + 10000, parent name FROM f2_directories);

В идеале запросы должны попадать в индексы на удаленном компьютере, чтобы при Я запускаю запрос с совпадающим томом.name на remote1, который будет быстрым, а также удаленным 2, но он чертовски медленен по сравнению с выполнением двух запросов FDW независимо (по причинам, связанным с местом, где происходит соединение)

Например,

select d.* from directories d INNER JOIN volume v on v.id = d.volume_id where v.name = 'vol1' limit 10; -- super slow; kills the indexes;

                              QUERY PLAN                                                                                                                                                                                                                                                                                                                                                                            
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=467.88..478.03 rows=5 width=336)
   ->  Hash Join  (cost=467.88..478.03 rows=5 width=336)
         Hash Cond: ("*SELECT* 1".volume_id = v.id)
         ->  Unique  (cost=242.28..247.50 rows=454 width=336)
               ->  Sort  (cost=242.28..242.51 rows=454 width=336)
                     Sort Key: "*SELECT* 1".id, "*SELECT* 1".valid, "*SELECT* 1".volume_id, "*SELECT* 1".parent_id, (("*SELECT* 1".depth)::integer), (("*SELECT* 1".inode)::numeric), (("*SELECT* 1".size)::bigint), (("*SELECT* 1".blocks)::bigint), (("*SELECT* 1".ctime)::timestamp with time zone), (("*SELECT* 1".atime)::timestamp with time zone), (("*SELECT* 1".mtime)::timestamp with time zone), (("*SELECT* 1".uid)::bigint), (("*SELECT* 1".gid)::bigint), (("*SELECT* 1".perms)::integer), "*SELECT* 1".path, "*SELECT* 1".name, "*SELECT* 1".rec_aggrs, "*SELECT* 1".local_aggrs, "*SELECT* 1".history_id, (("*SELECT* 1".sync_time)::timestamp with time zone), (("*SELECT* 1".out_of_sync_time)::timestamp with time zone), "*SELECT* 1".errors
                     ->  Append  (cost=100.00..238.27 rows=454 width=336)
                           ->  Subquery Scan on "*SELECT* 1"  (cost=100.00..119.08 rows=227 width=336)
                                 ->  Foreign Scan on dir_current  (cost=100.00..116.81 rows=227 width=336)
                           ->  Subquery Scan on "*SELECT* 2"  (cost=100.00..119.19 rows=227 width=336)
                                 ->  Foreign Scan on dir_current dir_current_1  (cost=100.00..116.92 rows=227 width=336)
         ->  Hash  (cost=225.58..225.58 rows=2 width=8)
               ->  Subquery Scan on v  (cost=225.54..225.58 rows=2 width=8)
                     ->  Unique  (cost=225.54..225.56 rows=2 width=289)
                           ->  Sort  (cost=225.54..225.54 rows=2 width=289)
                                 Sort Key: volume.id, volume.name, volume.inode, volume.check_noatime, volume.store_cifs_acl, volume.store_posix_acl, volume.dir_excludes, volume.file_excludes, volume.total_capacity, volume.capacity_set_manually, volume.default_agent_address, volume.display_name, volume.free_space, volume.free_space_set_manually, volume.type
                                 ->  Append  (cost=100.00..225.54 rows=2 width=289)
                                       ->  Foreign Scan on volume  (cost=100.00..112.76 rows=1 width=289)
                                       ->  Foreign Scan on volume volume_1  (cost=100.00..112.76 rows=1 width=289)
(19 rows)

Есть ли какие-либо советы о том, как сделать это с помощью скорректированных смещений для volume_id и по-прежнему использовать индексы? Я понимаю, что соединение происходит здесь в неоптимальном месте, после объединения, где мы не можем использовать удаленные индексы для volume_id, и мне, вероятно, нужно будет просто создать представления с объединенным в них именем. Но, конечно, любая групповая операция, вероятно, будет иметь похожие, ужасные результаты.

...