简体   繁体   English

我需要优化以下 pgsql select 语句——它目前平均需要 34 秒来执行

[英]I need to optimise the following pgsql select statement - its currently taking 34 avg seconds to execute

I have a view that shows all relations.我有一个显示所有关系的视图。

I use the following select for the view:我使用以下 select 作为视图:

CREATE VIEW relationships AS SELECT DISTINCT
    relations.name,
    sch_tco.id AS table_id,
    relations.related_table AS related_table,
    scd_tco.id AS related_id,
    relations.foreign_column AS foreign_column_name,
    relations.local_column AS local_column_name,
    count(DISTINCT relations.name) AS relationships,
    count(DISTINCT relations.referenced_tables) AS foreign_keys_count,
    count(DISTINCT relations.referencing_tables) AS references_count,
    count(DISTINCT related_table) AS related_tables_count,
    count(DISTINCT relations.referenced_tables) AS referenced_tables_count,
    count(DISTINCT relations.referencing_tables) AS referencing_tables_count
FROM ( SELECT DISTINCT
        pk_tco.table_name AS name,
        fk_tco.table_name AS related_table,
        fk_tco.table_name AS referencing_tables,
        NULL::varchar(100) AS referenced_tables,
        cc_tco.column_name AS foreign_column,
        pc_tco.column_name AS local_column
    FROM
        information_schema.referential_constraints rco
        JOIN information_schema.table_constraints fk_tco ON rco.constraint_name = fk_tco.constraint_name
            AND rco.constraint_schema = fk_tco.table_schema
        JOIN information_schema.table_constraints pk_tco ON rco.unique_constraint_name = pk_tco.constraint_name
            AND rco.unique_constraint_schema = pk_tco.table_schema
        JOIN information_schema.constraint_column_usage AS cc_tco ON cc_tco.constraint_name = pk_tco.constraint_name
            AND cc_tco.table_schema = pk_tco.table_schema
        JOIN information_schema.key_column_usage AS kc_tco ON kc_tco.constraint_name = pk_tco.constraint_name
            AND kc_tco.table_schema = pk_tco.table_schema
        JOIN information_schema.key_column_usage AS pc_tco ON pc_tco.constraint_name = fk_tco.constraint_name
            AND pc_tco.table_schema = fk_tco.table_schema
    GROUP BY
        name,
        related_table,
        referenced_tables,
        referencing_tables,
        foreign_column,
        local_column
    UNION ALL SELECT DISTINCT
        fk_tco.table_name AS name,
        pk_tco.table_name AS related_table,
        NULL AS referencing_tables,
        pk_tco.table_name AS referenced_tables,
        kc_tco.column_name AS foreign_column,
        pc_tco.column_name AS local_column
    FROM
        information_schema.referential_constraints rco
        JOIN information_schema.table_constraints fk_tco ON rco.constraint_name = fk_tco.constraint_name
            AND rco.constraint_schema = fk_tco.table_schema
        JOIN information_schema.table_constraints pk_tco ON rco.unique_constraint_name = pk_tco.constraint_name
            AND rco.unique_constraint_schema = pk_tco.table_schema
        JOIN information_schema.columns p ON fk_tco.table_name = p.table_name
        JOIN information_schema.columns t ON pk_tco.table_name = t.table_name
        JOIN information_schema.constraint_column_usage AS cc_tco ON cc_tco.constraint_name = fk_tco.constraint_name
            AND cc_tco.table_schema = fk_tco.table_schema
        JOIN information_schema.key_column_usage AS kc_tco ON kc_tco.constraint_name = pk_tco.constraint_name
            AND kc_tco.table_schema = pk_tco.table_schema
            AND kc_tco.position_in_unique_constraint = kc_tco.ordinal_position --IMPORTANT!
        JOIN information_schema.key_column_usage AS pc_tco ON pc_tco.constraint_name = fk_tco.constraint_name
            AND pc_tco.table_schema = fk_tco.table_schema
            AND pc_tco.position_in_unique_constraint = pc_tco.ordinal_position --IMPORTANT!
    GROUP BY
        name,
        related_table,
        referencing_tables,
        referenced_tables,
        foreign_column,
        local_column) relations
    JOIN tables sch_tco ON relations.name = sch_tco.name
    JOIN tables scd_tco ON relations.related_table = scd_tco.name
    JOIN information_schema.columns t ON sch_tco.name = t.table_name
    JOIN information_schema.columns p ON scd_tco.name = p.table_name
GROUP BY
    relations.name,
    related_table,
    table_id,
    related_id,
    foreign_column_name,
    local_column_name
ORDER BY
    relationships DESC;

It produces a table as follows它产生一个表如下

name名称 table_id表号 related_table相关表 related_id related_id foreign_column_name foreign_column_name local_column_name local_column_name relationships关系 foreign_keys_count foreign_keys_count references_count参考计数 related_tables_count related_tables_count referenced_tables_count referenced_tables_count referencing_tables_count referencing_tables_count
users用户 8298968d-54c9-496a-8320-bb67ffb5cfec 8298968d-54c9-496a-8320-bb67ffb5cfec configs配置 f954e6b8-111c-4ed7-b6d6-d68545640645 f954e6b8-111c-4ed7-b6d6-d68545640645 id ID user_id用户身份 1 1个 0 0 1 1个 1 1个 0 0 1 1个
users用户 8298968d-54c9-496a-8320-bb67ffb5cfec 8298968d-54c9-496a-8320-bb67ffb5cfec todos待办事项 d1de713a-5405-4bc6-80be-5c4c20d0343c d1de713a-5405-4bc6-80be-5c4c20d0343c id ID user_id用户身份 1 1个 0 0 1 1个 1 1个 0 0 1 1个

And then I use the following select to join tables table with the relations.然后我使用以下 select 将表与关系连接起来。 with the following select.与以下 select。

select  tables.id                                                                            id,
       tables.name                                                                          name,
       tables.parent                                                                        parent,
       (select jsonb_agg(relationships.*)
        from relationships
        where exists(select * from relationships where relationships.table_id = tables.id)) relations,
       (select distinct jsonb_agg(jsonb_build_object('name', cols.column_name, 'type', cols.udt_name))
        from information_schema.columns cols
        where cols.table_name = tables.name)                                                table_schema
from tables tables
         join relationships on relationships.table_id = tables.id
         join information_schema.columns table_cols on tables.name = table_cols.table_name
UNION
select  tables.id                                                                            id,
       tables.name                                                                          name,
       tables.parent                                                                        parent,
       (select jsonb_agg(relationships.*)
        from relationships
        where exists(select * from relationships where relationships.table_id = tables.id)) relations,
       (select distinct jsonb_agg(jsonb_build_object('name', cols.column_name, 'type', cols.udt_name))
        from information_schema.columns cols
        where cols.table_name = tables.name)                                                table_schema
from tables tables
         join information_schema.columns cols on tables.name = cols.table_name

This returns the correct data only it takes 35 seconds on average.这只返回正确的数据,平均只需要 35 秒。 I think its because I'm joining similar tables but I cant be certain.我认为这是因为我加入了类似的表格,但我不能确定。

I solved it with this query:我用这个查询解决了它:

select distinct tables.id,
                tables.name,
                tables.parent,
                (SELECT jsonb_agg(jsonb_build_object(
                        'table_schema', tc.table_schema,
                        'constraint_name', tc.constraint_name,
                        'table_name', tc.table_name,
                        'column_name', kcu.column_name,
                        'foreign_table_schema', ccu.table_schema,
                        'foreign_table_name', ccu.table_name,
                        'foreign_column_name', ccu.column_name))
                 FROM information_schema.table_constraints AS tc
                          JOIN information_schema.key_column_usage AS kcu
                               ON tc.constraint_name = kcu.constraint_name
                                   AND tc.table_schema = kcu.table_schema
                          JOIN information_schema.constraint_column_usage AS ccu
                               ON ccu.constraint_name = tc.constraint_name
                                   AND ccu.table_schema = tc.table_schema
                 WHERE tc.constraint_type = 'FOREIGN KEY' and ccu.table_name = tables.name) relationships,
                (select jsonb_agg(jsonb_build_object('name', cols.column_name, 'type', cols.udt_name))
                 from information_schema.columns cols
                 where cols.table_name = tables.name)      table_schema
from tables
         left join information_schema.columns table_cols on tables.name = table_cols.table_name

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM