Re: Slow query (wrong index used maybe)

Поиск
Список
Период
Сортировка
От salah jubeh
Тема Re: Slow query (wrong index used maybe)
Дата
Msg-id 1390843257.23746.YahooMailNeo@web164806.mail.gq1.yahoo.com
обсуждение исходный текст
Ответ на Slow query (wrong index used maybe)  (Stelian Iancu <stelian@iancu.ch>)
Ответы Re: Slow query (wrong index used maybe)
Список pgsql-performance
Hello Stelian, 

Have you tried to use func_table module?, I think it will help you to eliminate all the joins.

Regards


On Monday, January 27, 2014 5:54 PM, Stelian Iancu <stelian@iancu.ch> wrote:
Hello,

I have Postrgres 9.3 running on a Linux machine with 32GB RAM. I have a
fairly large database (some tables with approx. 1 mil. records) and I
have the following query:

    SELECT * FROM (
    SELECT DISTINCT c.ext_content_id AS type_1_id,
    "substring"(c.ext_content_id::text, 1, 13) AS type_1_album_id,
    cm1.value AS type_1_artist,
    cm2.value AS type_1_title,
    cm4.value AS type_1_duration,
    pm1.value AS type_1_icpn,
    cm3.value AS type_1_isrc,
    c.provider AS type_1_provider,
    to_number(cm5.value::text, '999999'::text) AS type_2_set_number,
    to_number(cm6.value::text, '999999'::text) AS type_2_track_number,
    cm7.value AS type_6_availability_ppd,
    cm12.value AS type_6_availability_sub,
    cm9.value AS type_1_language,
    cm11.value AS type_1_label_reporting_id,
    cm13.value AS type_1_parent_isrc
    FROM content c
    LEFT JOIN content_metadata cm1 ON c.content_id = cm1.content_id AND
    cm1.name::text = 'track_artist'::text
    LEFT JOIN content_metadata cm2 ON c.content_id = cm2.content_id AND
    cm2.name::text = 'track_title'::text
    LEFT JOIN content_metadata cm3 ON c.content_id = cm3.content_id AND
    cm3.name::text = 'track_isrc'::text
    LEFT JOIN content_metadata cm4 ON c.content_id = cm4.content_id AND
    cm4.name::text = 'track_duration'::text
    LEFT JOIN content_metadata cm5 ON c.content_id = cm5.content_id AND
    cm5.name::text = 'set_number'::text
    LEFT JOIN content_metadata cm6 ON c.content_id = cm6.content_id AND
    cm6.name::text = 'track_number'::text
    LEFT JOIN content_metadata cm7 ON c.content_id = cm7.content_id AND
    cm7.name::text = 'unlimited'::text
    LEFT JOIN content_metadata cm9 ON c.content_id = cm9.content_id AND
    cm9.name::text = 'language'::text
    LEFT JOIN content_metadata cm10 ON c.content_id = cm10.content_id
    AND cm10.name::text = 'import_date'::text
    LEFT JOIN content_metadata cm11 ON c.content_id = cm11.content_id
    AND cm11.name::text = 'label_reporting_id'::text
    LEFT JOIN content_metadata cm12 ON c.content_id = cm12.content_id
    AND cm12.name::text = 'subscription'::text
    LEFT JOIN content_metadata cm13 ON c.content_id = cm13.content_id
    AND cm13.name::text = 'parent_isrc'::text,
    product p
    LEFT JOIN product_metadata pm4 ON p.product_id = pm4.product_id AND
    pm4.name::text = 'product_title'::text
    LEFT JOIN product_metadata pm1 ON p.product_id = pm1.product_id AND
    pm1.name::text = 'upc'::text
    WHERE p.ext_product_id::text = substr(c.ext_content_id::text, 1, 13)
    ) view
    WHERE type_1_id='1-111-1027897-01-001';

Below are the definitions of the tables involved.

Content:

                      Table "public.content"
        Column      |            Type            | Modifiers
    -----------------+-----------------------------+-----------
    content_id      | bigint                      | not null
    status          | character varying(3)        | not null
    display_name    | character varying(1024)    | not null
    ext_content_id  | character varying(64)      | not null
    provider        | character varying(128)      | not null
    last_updated_by | character varying(30)      | not null
    last_updated_on | timestamp without time zone | not null
    created_by      | character varying(30)      | not null
    created_on      | timestamp without time zone | not null
    Indexes:
        "content_pkey" PRIMARY KEY, btree (content_id)
        "ak_key_2_content" UNIQUE, btree (ext_content_id, provider)
        "index_content_01" UNIQUE, btree (ext_content_id)
    Foreign-key constraints:
        "fk_content_01" FOREIGN KEY (provider) REFERENCES
        provider(ext_provider_id)
    Referenced by:
        TABLE "content_metadata" CONSTRAINT "fk_content_metadata_01"
        FOREIGN KEY (content_id) REFERENCES content(content_id)
        TABLE "packaged" CONSTRAINT "fk_packaged_reference_content"
        FOREIGN KEY (content_id) REFERENCES content(content_id)
        TABLE "product_content" CONSTRAINT "fk_product_content_01"
        FOREIGN KEY (content_id) REFERENCES content(content_id)
    Triggers:
        td_content BEFORE DELETE ON content FOR EACH ROW EXECUTE
        PROCEDURE trigger_fct_td_content()
        ti_content BEFORE INSERT ON content FOR EACH ROW EXECUTE
        PROCEDURE trigger_fct_ti_content()
        tu_content BEFORE UPDATE ON content FOR EACH ROW EXECUTE
        PROCEDURE trigger_fct_tu_content()
        tu_content_tree BEFORE UPDATE ON content FOR EACH ROW EXECUTE
        PROCEDURE trigger_fct_tu_content_tree()

Product:

                  Table "public.product"
        Column      |            Type            | Modifiers
    -----------------+-----------------------------+-----------
    product_id      | bigint                      | not null
    status          | character varying(3)        | not null
    display_name    | character varying(1024)    | not null
    ext_product_id  | character varying(64)      | not null
    last_updated_by | character varying(30)      | not null
    last_updated_on | timestamp without time zone | not null
    created_by      | character varying(30)      | not null
    created_on      | timestamp without time zone | not null
    Indexes:
        "product_pkey" PRIMARY KEY, btree (product_id)
        "ak_key_2_product" UNIQUE, btree (ext_product_id)
    Referenced by:
        TABLE "contract_product" CONSTRAINT "fk_contract_product_02"
        FOREIGN KEY (product_id) REFERENCES product(product_id)
        TABLE "offer_product" CONSTRAINT "fk_offer_product_01" FOREIGN
        KEY (product_id) REFERENCES product(product_id)
        TABLE "product_metadata" CONSTRAINT
        "fk_product__reference_product" FOREIGN KEY (product_id)
        REFERENCES product(product_id)
        TABLE "product_content" CONSTRAINT "fk_product_content_02"
        FOREIGN KEY (product_id) REFERENCES product(product_id)
    Triggers:
        td_product BEFORE DELETE ON product FOR EACH ROW EXECUTE
        PROCEDURE trigger_fct_td_product()
        ti_product BEFORE INSERT ON product FOR EACH ROW EXECUTE
        PROCEDURE trigger_fct_ti_product()
        tu_product BEFORE UPDATE ON product FOR EACH ROW EXECUTE
        PROCEDURE trigger_fct_tu_product()
        tu_product_tree BEFORE UPDATE ON product FOR EACH ROW EXECUTE
        PROCEDURE trigger_fct_tu_product_tree()

Product_metadata:

              Table "public.product_metadata"
        Column      |            Type            | Modifiers
    -----------------+-----------------------------+-----------
    product_id      | bigint                      | not null
    name            | character varying(64)      | not null
    distributor_id  | bigint                      |
    value          | character varying(4000)    |
    created_on      | timestamp without time zone | not null
    created_by      | character varying(30)      | not null
    last_updated_on | timestamp without time zone | not null
    last_updated_by | character varying(30)      | not null
    Indexes:
        "idx_product_metadata_03" btree (name, value)
        "index_product_metadata_02" btree (product_id, name)
        "index_product_metadata_cid" btree (product_id)
    Foreign-key constraints:
        "fk_product__reference_product" FOREIGN KEY (product_id)
        REFERENCES product(product_id)
        "fk_product_metadata_02" FOREIGN KEY (distributor_id) REFERENCES
        operator(operator_id)
    Triggers:
        td_product_metadata BEFORE DELETE ON product_metadata FOR EACH
        ROW EXECUTE PROCEDURE trigger_fct_td_product_metadata()
        ti_product_metadata BEFORE INSERT ON product_metadata FOR EACH
        ROW EXECUTE PROCEDURE trigger_fct_ti_product_metadata()
        tu_product_metadata BEFORE UPDATE ON product_metadata FOR EACH
        ROW EXECUTE PROCEDURE trigger_fct_tu_product_metadata()

Content_metadata:

              Table "public.content_metadata"
        Column      |            Type            | Modifiers
    -----------------+-----------------------------+-----------
    content_id      | bigint                      | not null
    name            | character varying(64)      | not null
    distributor_id  | bigint                      |
    value          | character varying(4000)    |
    last_updated_by | character varying(30)      | not null
    last_updated_on | timestamp without time zone | not null
    created_by      | character varying(30)      | not null
    created_on      | timestamp without time zone | not null
    Indexes:
        "idx_content_metadata_03" btree (name, value)
        "idx_content_metadata_04" btree (content_id, name, value)
        "index_content_metadata_02" btree (content_id, name)
        "index_content_metadata_cid" btree (content_id)
    Foreign-key constraints:
        "fk_content_metadata_01" FOREIGN KEY (content_id) REFERENCES
        content(content_id)
        "fk_content_metadata_02" FOREIGN KEY (distributor_id) REFERENCES
        operator(operator_id)
    Triggers:
        td_content_metadata BEFORE DELETE ON content_metadata FOR EACH
        ROW EXECUTE PROCEDURE trigger_fct_td_content_metadata()
        ti_content_metadata BEFORE INSERT ON content_metadata FOR EACH
        ROW EXECUTE PROCEDURE trigger_fct_ti_content_metadata()
        tu_content_metadata BEFORE UPDATE ON content_metadata FOR EACH
        ROW EXECUTE PROCEDURE trigger_fct_tu_content_metadata()

The query as it is takes approx. 35 seconds, which is very bad. If I
take out the line:

    LEFT JOIN product_metadata pm4 ON p.product_id = pm4.product_id AND
    pm4.name::text = 'product_title'::text

then the time is under 1 second.

Here you can see the plan for the query (as it is here, i.e. when it
takes a lot of time): http://explain.depesz.com/s/K9s

As far as I can see, the wrong index is used. In the lines

    "->  Bitmap Heap Scan on product_metadata pm4
    (cost=6014.11..257694.54 rows=579474 width=8) (actual
    time=282.364..13005.344 rows=557834 loops=1)"
        "Recheck Cond: ((name)::text = 'product_title'::text)"
        "Buffers: shared read=175851"
        "->  Bitmap Index Scan on idx_product_metadata_03
        (cost=0.00..5869.24 rows=579474 width=0) (actual
        time=222.724..222.724 rows=557834 loops=1)"
            "Index Cond: ((name)::text = 'product_title'::text)"
            "Buffers: shared read=3953"

it can be seen that it uses idx_product_metadata_03 which is on (name,
value). Shouldn't it use index_product_metadata_02 which is on
(product_id, name)?

Or is there another reason why this query is so slow?

I have changed some of the default settings of Postgres as follows:

random_page_cost = 1.4
cpu_index_tuple_cost = 0.00001
effective_cache_size = 256MB
work_mem = 300MB

If you need any other information, let me know.

Thanks in advance!

With regards,
Stelian Iancu


--
Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance


В списке pgsql-performance по дате отправления:

Предыдущее
От: Tom Lane
Дата:
Сообщение: Re: Slow query (wrong index used maybe)
Следующее
От: Stelian Iancu
Дата:
Сообщение: Re: Slow query (wrong index used maybe)