0

Я использую PostgreSQL 8.4. Как лучше всего оптимизировать этот запрос:Оптимизация SELECT DISTINCT

SELECT DISTINCT campaigns.* FROM campaigns 
LEFT JOIN adverts ON campaign_id = campaigns.id 
LEFT JOIN shops ON campaigns.shop_id = shops.id 
LEFT JOIN exports_adverts ON advert_id = adverts.id 
LEFT JOIN exports ON export_id = exports.id 
LEFT JOIN rotations ON rotations.advert_id = adverts.id 
LEFT JOIN blocks ON block_id = blocks.id 
WHERE 
    (shops.is_active = TRUE) 
    AND exports.user_id = any(uids) 
    OR blocks.user_id = any(uids) 
    AND campaigns.id = any(ids) 

Мои таблицы является:

CREATE TABLE campaigns (
    id integer NOT NULL, 
    shop_id integer NOT NULL, 
    title character varying NOT NULL, 
    ... 
); 

CREATE TABLE adverts (
    id integer NOT NULL, 
    campaign_id integer NOT NULL, 
    title character varying NOT NULL, 
    ... 
); 

CREATE TABLE shops (
    id integer NOT NULL, 
    title character varying NOT NULL, 
    is_active boolean DEFAULT true NOT NULL, 
    ... 
); 

CREATE TABLE exports (
    id integer NOT NULL, 
    title character varying, 
    user_id integer NOT NULL, 
    ... 
); 

CREATE TABLE exports_adverts (
    id integer NOT NULL, 
    export_id integer NOT NULL, 
    advert_id integer NOT NULL, 
    ... 
); 

CREATE TABLE rotations (
    id integer NOT NULL, 
    block_id integer NOT NULL, 
    advert_id integer NOT NULL, 
    ... 
); 

CREATE TABLE blocks (
    id integer NOT NULL, 
    title character varying NOT NULL, 
    user_id integer NOT NULL, 
    ... 
); 

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

EXPLAIN для запроса:

Unique (cost=284529.95..321207.47 rows=57088 width=106) (actual time=508048.104..609870.600 rows=106 loops=1) 
-> Sort (cost=284529.95..286567.59 rows=815056 width=106) (actual time=508048.102..602413.688 rows=8354563 loops=1) 
    Sort Key: campaigns.id, campaigns.shop_id, campaigns.title 
    Sort Method: external merge Disk: 1017136kB 
    -> Hash Left Join (cost=2258.33..62419.56 rows=815056 width=106) (actual time=49.509..17510.009 rows=8354563 loops=1) 
     Hash Cond: (rotations.block_id = blocks.id) 
     -> Merge Right Join (cost=1719.44..44560.73 rows=815056 width=110) (actual time=42.194..12317.422 rows=8354563 loops=1) 
     Merge Cond: (rotations.advert_id = adverts.id) 
     -> Index Scan using rotations_advert_id_key on rotations (cost=0.00..29088.30 rows=610999 width=8) (actual time=0.040..3026.898 rows=610999 loops=1) 
     -> Sort (cost=1719.44..1737.90 rows=7386 width=110) (actual time=42.144..3965.416 rows=8354563 loops=1) 
      Sort Key: adverts.id 
      Sort Method: external sort Disk: 1336kB 
      -> Hash Left Join (cost=739.01..1244.87 rows=7386 width=110) (actual time=10.519..21.351 rows=10571 loops=1) 
       Hash Cond: (exports_adverts.export_id = exports.id) 
       -> Hash Left Join (cost=715.60..1119.90 rows=7386 width=114) (actual time=10.178..17.472 rows=10571 loops=1) 
       Hash Cond: (adverts.id = exports_adverts.advert_id) 
       -> Hash Left Join (cost=304.71..433.53 rows=2781 width=110) (actual time=3.614..5.106 rows=3035 loops=1) 
        Hash Cond: (campaigns.id = adverts.campaign_id) 
        -> Hash Join (cost=1.13..9.32 rows=112 width=106) (actual time=0.051..0.303 rows=106 loops=1) 
         Hash Cond: (campaigns.shop_id = shops.id) 
         -> Seq Scan on campaigns (cost=0.00..6.23 rows=223 width=106) (actual time=0.011..0.150 rows=223 loops=1) 
         -> Hash (cost=1.08..1.08 rows=4 width=4) (actual time=0.015..0.015 rows=4 loops=1) 
         -> Seq Scan on shops (cost=0.00..1.08 rows=4 width=4) (actual time=0.010..0.012 rows=4 loops=1) 
          Filter: is_active 
        -> Hash (cost=234.37..234.37 rows=5537 width=8) (actual time=3.546..3.546 rows=5537 loops=1) 
         -> Seq Scan on adverts (cost=0.00..234.37 rows=5537 width=8) (actual time=0.010..2.200 rows=5537 loops=1) 
       -> Hash (cost=227.06..227.06 rows=14706 width=8) (actual time=6.532..6.532 rows=14706 loops=1) 
        -> Seq Scan on exports_adverts (cost=0.00..227.06 rows=14706 width=8) (actual time=0.016..3.028 rows=14706 loops=1) 
       -> Hash (cost=14.85..14.85 rows=685 width=4) (actual time=0.311..0.311 rows=685 loops=1) 
       -> Seq Scan on exports (cost=0.00..14.85 rows=685 width=4) (actual time=0.014..0.156 rows=685 loops=1) 
     -> Hash (cost=368.95..368.95 rows=13595 width=4) (actual time=7.281..7.281 rows=13595 loops=1) 
     -> Seq Scan on blocks (cost=0.00..368.95 rows=13595 width=4) (actual time=0.027..3.990 rows=13595 loops=1) 
+0

Вы говорите, ваш запрос медленно? –

+0

Да! 106 строк (0) Общая продолжительность выполнения: 599,489.968 мс Выполнен SQL. Дополнительная информация? – DToch

+0

Сколько строк в общей сложности для всех 7 таблиц? Это может быть разумным временем, если таблицы содержат миллионы строк. –

ответ

0

Расщепление or в 2 союзные запросы могут помочь (без DISTINCT):

SELECT campaigns.* 
FROM campaigns 
    LEFT JOIN adverts ON campaign_id = campaigns.id 
    LEFT JOIN shops ON campaigns.shop_id = shops.id 
    LEFT JOIN exports_adverts ON advert_id = adverts.id 
    LEFT JOIN exports ON export_id = exports.id 
    LEFT JOIN rotations ON rotations.advert_id = adverts.id 
    LEFT JOIN blocks ON block_id = blocks.id 
WHERE 
    (shops.is_active = TRUE) 
    AND exports.user_id = any(uids) 

UNION 

SELECT campaigns.* 
FROM campaigns 
    LEFT JOIN adverts ON campaign_id = campaigns.id 
    LEFT JOIN shops ON campaigns.shop_id = shops.id 
    LEFT JOIN exports_adverts ON advert_id = adverts.id 
    LEFT JOIN exports ON export_id = exports.id 
    LEFT JOIN rotations ON rotations.advert_id = adverts.id 
    LEFT JOIN blocks ON block_id = blocks.id 
WHERE 
    blocks.user_id = any(uids) 
    AND campaigns.id = any(ids) 
+0

Я только что заметил его очень старый вопрос .... – Wojtas