Ускорение PostgreSQL запросов (Проверьте, существует ли запись в другой таблице) - PullRequest
0 голосов
/ 27 апреля 2020

Мне нужна помощь, чтобы улучшить скорость запроса.

У меня есть 3 таблицы:
1- pairTable2 таблица из 4 столбцов:
- genomic_accession: группировка столбца (все равно для этого вопроса)
- сборка: столбец группировки (не волнует этот вопрос)
- product_accession: столбец, используемый для поиска в другой таблице
- tmpcol: столбец, используемый для поиска в другой таблице
2- SBPDB таблица из 1 столбца:
- product_accession: столбец, используемый для поиска в другой таблице
3- cacheDB таблица из 1 столбца: - product_accession: столбец, используемый для поиска в другой таблице

Идея заключается в создании логического столбца с именем SBP в таблице 1, который равен TRUE, если значение столбцов product_accession и / или tmpcol находится в уникальном столбце в SBPDB;
И создайте логический столбец с именем SBP в таблице 1, равное TRUE, если значение в столбцах product_accession и / или tmpcol находится в уникальном столбце в cacheDB.

Я использую R с DBI и dplyr в качестве бэкэнда, тогда запрос может выглядеть странно. Но я пытаюсь выполнить следующий запрос:

SELECT "genomic_accession", 
       "assembly", 
       "product_accession", 
       "tmpcol", 
       "product_accession" IN (SELECT product_accession 
                               FROM   "cachedb") 
        OR "tmpcol" IN (SELECT product_accession 
                        FROM   "cachedb") AS "CACHE", 
       "product_accession" IN (SELECT product_accession 
                               FROM   "sbpdb") 
        OR "tmpcol" IN (SELECT product_accession 
                        FROM   "sbpdb")   AS "SBP" 
FROM   (SELECT * 
        FROM   "pairtable2" 
        LIMIT  500000) "dbplyr_031";

(см. Объяснение)

                                       QUERY PLAN                                       
----------------------------------------------------------------------------------------
 Subquery Scan on dbplyr_031  (cost=3242.27..3846856408.45 rows=500000 width=59)
   ->  Limit  (cost=0.00..10666.17 rows=500000 width=57)
         ->  Seq Scan on "pairTable2"  (cost=0.00..781515.16 rows=36635216 width=57)
   SubPlan 1
     ->  Seq Scan on "cacheDB"  (cost=0.00..1394.91 rows=90491 width=14)
   SubPlan 2
     ->  Seq Scan on "cacheDB" "cacheDB_1"  (cost=0.00..1394.91 rows=90491 width=14)
   SubPlan 3
     ->  Materialize  (cost=0.00..7001.57 rows=276838 width=14)
           ->  Seq Scan on "SBPDB"  (cost=0.00..4265.38 rows=276838 width=14)
   SubPlan 4
     ->  Materialize  (cost=0.00..7001.57 rows=276838 width=14)
           ->  Seq Scan on "SBPDB" "SBPDB_1"  (cost=0.00..4265.38 rows=276838 width=14)
(13 rows)

Итак, это всего лишь выборка из 500 тыс. Строк и через 1 час Все еще работает. Общее количество строк:

genomes=> select count(*) from "pairTable2";
  count   
----------
 36633962
(1 row)

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

Пример таблиц:
(1)

 genomic_accession |    assembly     | product_accession |     tmpcol     
-------------------+-----------------+-------------------+----------------
 NC_007777.1       | GCF_000013345.1 | WP_011437108.1    | WP_011437109.1
 NC_007777.1       | GCF_000013345.1 | WP_011437109.1    | WP_011437110.1
 NC_007777.1       | GCF_000013345.1 | WP_011437110.1    | WP_011437113.1
 NC_007777.1       | GCF_000013345.1 | WP_011437113.1    | WP_011437114.1
 NC_007777.1       | GCF_000013345.1 | WP_011437114.1    | WP_011437116.1
 NC_007777.1       | GCF_000013345.1 | WP_011437116.1    | WP_011437117.1
 NC_007777.1       | GCF_000013345.1 | WP_011437117.1    | WP_011437118.1
 NC_007777.1       | GCF_000013345.1 | WP_011437118.1    | WP_011437120.1
 NC_007777.1       | GCF_000013345.1 | WP_011437120.1    | WP_011437121.1
 NC_007777.1       | GCF_000013345.1 | WP_011437121.1    | WP_011437123.1
(10 rows)

(2)

 product_accession 
-------------------
 WP_005887071.1
 WP_005913801.1
 WP_002804432.1
 WP_010366489.1
 WP_012444785.1
 NP_636898.1
 WP_046342269.1
 WP_074057745.1
 WP_039420813.1
 WP_005932253.1
(10 rows)

(3)

 product_accession 
-------------------
 ABG85315.1
 ABG85570.1
 ABG86033.1
 ABG86301.1
 ABG87594.1
 ACX82524.1
 ACX83274.1
 ACX83416.1
 ADX79866.1
 ADX79880.1
(10 rows)

Пример вывода:

 genomic_accession |    assembly     | product_accession |     tmpcol     | CACHE | SBP 
-------------------+-----------------+-------------------+----------------+-------+-----
 NC_007899.1       | GCF_000009945.1 | WP_011457581.1    | WP_011457582.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457582.1    | WP_011457583.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457583.1    | WP_011457584.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457584.1    | WP_011457585.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457585.1    | WP_011457586.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457586.1    | WP_011457587.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457587.1    | WP_011457588.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457588.1    | WP_011457589.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457589.1    | WP_011457590.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457590.1    | WP_011457592.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457592.1    | WP_011457593.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457593.1    | WP_011457594.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457594.1    | WP_011457596.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457596.1    | WP_011457597.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457597.1    | WP_011457598.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457598.1    | WP_011457600.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457600.1    | WP_011457601.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457601.1    | WP_011457602.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457602.1    | WP_011457603.1 | f     | f
 NC_007899.1       | GCF_000009945.1 | WP_011457603.1    | WP_011457604.1 | f     | f

Заранее спасибо

1 Ответ

1 голос
/ 27 апреля 2020

Это ваш запрос:

SELECT "genomic_accession", "assembly", "product_accession", "tmpcol",
       ("product_accession" IN ( SELECT product_accession FROM "cacheDB" ) OR
        "tmpcol" IN ( SELECT product_accession FROM "cacheDB")
       ) AS "CACHE",
       ("product_accession" IN ( SELECT product_accession FROM "SBPDB" ) OR
        "tmpcol" IN ( SELECT product_accession FROM "SBPDB" ) AS "SBP"
FROM (SELECT * FROM "pairTable2" LIMIT 500000) "dbplyr_031";

Я бы избавился от всех двойных кавычек. Не создавайте имена столбцов и таблиц, которые необходимо экранировать. Тогда EXISTS с правильными индексами часто работает лучше:

SELECT "genomic_accession", "assembly", "product_accession", "tmpcol",
       (EXISTS (SELECT 1
                FROM "cacheDB" c
                *WHERE c.product_accession IN (pt.product_accession, pt.tmpcol ) 
               )
       ) AS CACHE,
       (EXISTS (SELECT 1
                FROM "SBPDB" s
                WHERE s.product_accession IN (pt.product_accession, pt.tmpcol ) 
               )
       ) AS SBP
FROM (SELECT * FROM "pairTable2" LIMIT 500000) pt;

Затем для производительности вам нужны индексы на cachedb(product_accession) и sbpdb(product_accession).

...