2016-12-01 4 views
0
  • пункт Список

mydbab=# \d+ table1;PostgreSQL медленный запрос, заказ по LIMIT

    Table "dbmydb.table1" 
    Column  | Type | Modifiers | Scol5rage | Stats target | Description 
----------------+---------+-----------+------------+--------------+------------- 
pk    | bigint | not null | plain  |    | 
col1   | bigint | not null | plain  |    | 
col2   | citext | not null | extended |    | 
col3   | citext |   | extended |    |   
col4   | citext | not null | extended |    | 
col5   | citext |   | extended |    | 
col6   | citext |   | extended |    | 
bcol7   | citext |   | extended |    | 
col8   | citext |   | extended |    | 
col9   | citext |   | extended |    | 
col10   | bigint | not null | plain  |    | 
col11   | citext |   | extended |    | 
col12   | bigint |   | plain  |    |  
col13   | integer | default 1 | plain  |    | 
col14   | integer | default 0 | plain  |    | 
col15   | bigint |   | plain  |    | 
col16   | integer | default 0 | plain  |    | 
col17   | integer | default 0 | plain  |    |  
col18   | integer | default 0 | plain  |    | 
col19   | citext |   | extended |    | 
col20   | citext |   | extended |    | 
col21   | citext |   | extended |    | 

Индексы:

"table1_pk" PRIMARY KEY, btree (pk) 
"table1_idx3" btree (col10) 
"table1_idx4" btree ("col4") 
"table1_idx5" btree (col11) 
"table1_idx6" btree (col15) 
"table1_fk_idx" btree (col1) 

проверочные ограничения:

"table1_col6_c" CHECK (length(col6::text) <= 5000) 
"table1_col4_c" CHECK (length("col4"::text) <= 253) 
"table1_col5_c” CHECK (length(col5::text) <= 5000) 
"table1_col3_c" CHECK (length(col3::text) <= 253) 
"table1_col11_c" CHECK (length(col11::text) <= 253) 
"table1_col20_c” CHECK (length(col20::text) <= 200) 
"table1_col21_c” CHECK (length(col21::text) <= 500) 
"table1_col7_c” CHECK (length(col7::text) <= 500) 
"table1_col9_c" CHECK (length(col9::text) <= 100) 
"table1_col5_c" CHECK (length("col5"::text) <= 5000) 
"table1_col19_c” CHECK (length(col19::text) <= 100) 

ограничения внешнего ключа:

"table1_fk" FOREIGN KEY (col1) REFERENCES table2(col1) ON DELETE CASCADE 

Ссылочные по:

TABLE “table3” CONSTRAINT “table3_fk2" FOREIGN KEY (pk) REFERENCES table1(pk) ON DELETE CASCADE 
TABLE “table4” CONSTRAINT “table4_fk2" FOREIGN KEY (pk) REFERENCES table1(pk) ON DELETE CASCADE 
TABLE “table5” CONSTRAINT “table5_fk1" FOREIGN KEY (pk) REFERENCES table1(pk) 
TABLE “table6” CONSTRAINT “table6_fk" FOREIGN KEY (pk) REFERENCES table1(pk) ON DELETE CASCADE 
TABLE “table7” CONSTRAINT “table7_fk1" FOREIGN KEY (pk) REFERENCES table1(pk) ON DELETE CASCADE 

Параметры: autovacuum_vacuum_scale_factor=0.05

QUERY PLAN

explain SELECT * FROM table1 WHERE ((table1.col1 = 814000000002054) AND (((table1.pk >= 238000000000000) AND (table1.pk <= 238999999999999)) OR ((table1.pk >= 0) AND (table1.pk <= 999999999999)))) ORDER BY table1.col15 DESC LIMIT 7 
(query gets timed out for explain analyze) 

Limit (cost=0.56..607.64 rows=7 width=603) 

Index Scan Backward using table1_idx6 on table1 (cost=0.56..12622561.13 rows=145548 width=603) Filter: ((col1 = 814000000002054::bigint) AND (((pk >= 238000000000000::bigint) AND (pk <= 238999999999999::bigint)) OR ((pk >= 0) AND (pk <= 999999999999::bigint)))) 

Задача: Стол имеет 50M записей. Этот запрос занимает более 15 минут для запуска! Мы откалибровали до автоматического вакуума до 0,05. Автоанализ находится по умолчанию в PG. запрос был даже изменен на ORDER BY table1.col15 ASC LIMIT 7, даже если запрос выполняется примерно в одно и то же время. Операция Insert/Update занимает только ms.

История: Результат используется, чтобы быть быстрее, когда она имеет меньшие данные - запросов не были никаких проблем в MySQL, мигрировали в Pg несколько недель назад.

Worker_mem - 956MB.

select version();

PostgreSQL 9.4.0 on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-54), 64-bit 
(1 row) 
+0

Сколько записей (% от общего числа) соответствует 'col1 = 814000000002054'? Если значение меньше 5-10%, в этом столбце должен использоваться индекс. – Andreas

+0

Пожалуйста, исправьте свое форматирование и отбросьте свой вопрос на что-то более усваиваемое. –

+0

@ У Andreas было бы около 2 миллионов записей в таблице с col1 = 814000000002054 – stonelazy

ответ

0

Попробуйте создать индекс в нескольких столбцов:

CREATE INDEX ON table1(col15, col1, pk); 
+0

если вы могли бы объяснить, как это будет улучшаться? (пользовательские данные sharding на PK fyi), и, кроме того, это не значит, что запрос здесь неэффективен. – stonelazy

Смежные вопросы