Медленный sql statments, есть ли способ изменить это? - PullRequest
0 голосов
/ 02 декабря 2010

У нашего приложения очень медленное утверждение, оно занимает более 11 секунд, поэтому я хочу знать, есть ли способ его оптимизации?

Оператор SQL

SELECT id FROM mapfriends.cell_forum_topic WHERE id in   (
SELECT topicid FROM mapfriends.cell_forum_item WHERE skyid=103230293 GROUP BY topicid ) 
AND categoryid=29 AND hidden=false   ORDER BY restoretime DESC LIMIT 10 OFFSET 0;

   id    
---------
 2471959
 2382296
 1535967
 2432006
 2367281
 2159706
 1501759
 1549304
 2179763
 1598043
(10 rows)

Time: 11444.976 ms

План

friends=> explain SELECT id FROM friends.cell_forum_topic WHERE id in   (
friends(> SELECT topicid FROM friends.cell_forum_item WHERE skyid=103230293 GROUP BY topicid) 
friends-> AND categoryid=29 AND hidden=false   ORDER BY restoretime DESC LIMIT 10 OFFSET 0;
                                                          QUERY PLAN                                                           
-------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=1443.15..1443.15 rows=2 width=12)
   ->  Sort  (cost=1443.15..1443.15 rows=2 width=12)
         Sort Key: cell_forum_topic.restoretime
         ->  Nested Loop  (cost=1434.28..1443.14 rows=2 width=12)
               ->  HashAggregate  (cost=1434.28..1434.30 rows=2 width=4)
                     ->  Index Scan using cell_forum_item_idx_skyid on cell_forum_item  (cost=0.00..1430.49 rows=1516 width=4)
                           Index Cond: (skyid = 103230293)
               ->  Index Scan using cell_forum_topic_pkey on cell_forum_topic  (cost=0.00..4.40 rows=1 width=12)
                     Index Cond: (cell_forum_topic.id = cell_forum_item.topicid)
                     Filter: ((NOT cell_forum_topic.hidden) AND (cell_forum_topic.categoryid = 29))
(10 rows)

Time: 1.109 ms

Индексы

friends=> \d cell_forum_item
                                   Table "friends.cell_forum_item"
 Column  |              Type              |                          Modifiers                           
---------+--------------------------------+--------------------------------------------------------------
 id      | integer                        | not null default nextval('cell_forum_item_id_seq'::regclass)
 topicid | integer                        | not null
 skyid   | integer                        | not null
 content | character varying(200)         | 
 addtime | timestamp(0) without time zone | default now()
 ischeck | boolean                        | 
Indexes:
    "cell_forum_item_pkey" PRIMARY KEY, btree (id)
    "cell_forum_item_idx" btree (topicid, skyid)
    "cell_forum_item_idx_1" btree (topicid, id)
    "cell_forum_item_idx_skyid" btree (skyid)
friends=> \d cell_forum_topic
                                                 Table "friends.cell_forum_topic"
   Column    |              Type              |                                      Modifiers                                      

-------------+--------------------------------+-------------------------------------------------------------------------------------
-
 id          | integer                        | not null default nextval(('"friends"."cell_forum_topic_id_seq"'::text)::regclass)
 categoryid  | integer                        | not null
 topic       | character varying              | not null
 content     | character varying              | not null
 skyid       | integer                        | not null
 addtime     | timestamp(0) without time zone | default now()
 reference   | integer                        | default 0
 restore     | integer                        | default 0
 restoretime | timestamp(0) without time zone | default now()
 locked      | boolean                        | default false
 settop      | boolean                        | default false
 hidden      | boolean                        | default false
 feature     | boolean                        | default false
 picid       | integer                        | default 29249
 managerid   | integer                        | 
 imageid     | integer                        | default 0
 pass        | boolean                        | default false
 ischeck     | boolean                        | 
Indexes:
    "cell_forum_topic_pkey" PRIMARY KEY, btree (id)
    "idx_cell_forum_topic_1" btree (categoryid, settop, hidden, restoretime, skyid)
    "idx_cell_forum_topic_2" btree (categoryid, hidden, restoretime, skyid)
    "idx_cell_forum_topic_3" btree (categoryid, hidden, restoretime)
    "idx_cell_forum_topic_4" btree (categoryid, hidden, restore)
    "idx_cell_forum_topic_5" btree (categoryid, hidden, restoretime, feature)
    "idx_cell_forum_topic_6" btree (categoryid, settop, hidden, restoretime)

Объяснить, проанализировать

mapfriends=> explain analyze SELECT id FROM mapfriends.cell_forum_topic 
mapfriends->   join (SELECT topicid FROM mapfriends.cell_forum_item WHERE     skyid=103230293 GROUP BY topicid) as tmp
mapfriends->  on mapfriends.cell_forum_topic.id=tmp.topicid
mapfriends->   where categoryid=29 AND hidden=false ORDER BY restoretime  DESC   LIMIT 10 OFFSET 0;
                                                                                    QUERY PLAN                                      

------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------
 Limit  (cost=1446.89..1446.90 rows=2 width=12) (actual time=18016.006..18016.013 rows=10 loops=1)
   ->  Sort  (cost=1446.89..1446.90 rows=2 width=12) (actual time=18016.001..18016.002 rows=10 loops=1)
         Sort Key: cell_forum_topic.restoretime
         Sort Method:  quicksort  Memory: 25kB
         ->  Nested Loop  (cost=1438.02..1446.88 rows=2 width=12) (actual time=16988.492..18015.869 rows=20 loops=1)
               ->  HashAggregate  (cost=1438.02..1438.04 rows=2 width=4) (actual time=15446.735..15447.243 rows=610 loops=1)
                     ->  Index Scan using cell_forum_item_idx_skyid on cell_forum_item  (cost=0.00..1434.22 rows=1520 width=4) (actual time=302.378..15429.782 rows=7133 loops=1)
                           Index Cond: (skyid = 103230293)
               ->  Index Scan using cell_forum_topic_pkey on cell_forum_topic  (cost=0.00..4.40 rows=1 width=12) (actual time=4.210..4.210 rows=0 loops=610)
                     Index Cond: (cell_forum_topic.id = cell_forum_item.topicid)
                     Filter: ((NOT cell_forum_topic.hidden) AND (cell_forum_topic.categoryid = 29))
 Total runtime: 18019.461 ms

Ответы [ 2 ]

1 голос
/ 02 декабря 2010

Не могли бы вы дать нам больше информации о таблицах (статистике) и конфигурации?

SELECT version();
SELECT category, name, setting FROM pg_settings WHERE name IN('effective_cache_size', 'enable_seqscan', 'shared_buffers');
SELECT * FROM pg_stat_user_tables WHERE relname IN('cell_forum_topic', 'cell_forum_item');
SELECT * FROM pg_stat_user_indexes WHERE relname IN('cell_forum_topic', 'cell_forum_item');
SELECT * FROM pg_stats WHERE tablename IN('cell_forum_topic', 'cell_forum_item');

И прежде чем получать эти данные, используйте ANALYZE.

Похоже, у вас проблема с индексом, вот где весь запрос тратит все свое время:

-> Сканирование индекса с помощью cell_forum_item_idx_skyid on cell_forum_item (стоимость = 0.00..1434.22 ряды = 1520 ширина = 4) (фактический время = 302,378.,15429,782 строк = 7133 петли = 1)

Если вы используете VACUUM FULL на регулярной основе (НЕ РЕКОМЕНДУЕТСЯ!), Проблема может быть в раздувании индекса. REINDEX может быть хорошей идеей, просто чтобы быть уверенным:

REINDEX TABLE cell_forum_item;

А если говорить об индексах, вы можете отбросить пару из них, они устарели:

"idx_cell_forum_topic_6" btree (categoryid, settop, hidden, restoretime)
"idx_cell_forum_topic_3" btree (categoryid, hidden, restoretime)

Другие индексы имеют те же данные и могут использоваться базой данных.


Похоже, у вас есть пара проблем:

  • автовакуум выключен или работает позади. Последний автовакуум был включен 2010-12-02 и у вас 256734 мертвых кортежи в одном столе и 451430 мертвых одни в другой .... надо делать что-то об этом, это серьезная проблема.
  • Когда автовакуум снова работает, вы должен сделать ВАКУУМ ПОЛНЫЙ и REINDEX, чтобы заставить таблицу переписать и избавиться от всего пустого пространства в вашем таблицы.
  • после устранения проблемы с вакуумом вы надо также анализировать: база данных ожидает 1520 результатов, но получает 7133 Результаты. Это может быть проблемой с статистика, может быть, вам придется увеличить СТАТИСТИКА .
  • Сам запрос нуждается в переписывании а также: он получает 7133 результатов, но это нужно всего 610 результатов. Более 90% результаты теряются ... и получать эти 7133 занимают много времени, более 15 секунд Избавьтесь от подзапроса, используя JOIN без GROUP BY или EXISTS, также без GROUP BY.

Но сначала включите автоочистку, пока не возникли новые или другие проблемы.

0 голосов
/ 02 декабря 2010

проблема не в отсутствии кэширования плана запроса, а, скорее всего, из-за выбора плана из-за отсутствия соответствующих индексов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...