0

PostgreSQL 8.4 を使用しています。このクエリを最適化するのに最適なものは次のとおりです。

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)
4

1 に答える 1

0

2 つのユニオン クエリに分割orすると役立つ場合があります (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)
于 2013-11-07T21:57:51.220 に答える