Мой удаленный запрос Postgres кажется зависшим навсегда - PullRequest
0 голосов
/ 12 октября 2018

Я выполняю следующий запрос на удаленном экземпляре Postgres с локального клиента:

select * from matches_tb1 order by match_id desc limit 10;

matches_tb1 является внешней таблицей и имеет match_id в качестве уникального индекса.Похоже, запрос зависает навсегда.Когда я использую explain verbose, к «Удаленному SQL» не добавляется ORDER BY.Я предполагаю, что локальный сервер не выполнил заказ на удаленный сервер.Как я могу решить эту проблему?

Прилагаются объяснения результатов:

 explain verbose select match_id from matches_tb1 order by match_id desc limit 10;
                                            QUERY PLAN                                             
---------------------------------------------------------------------------------------------------
 Limit  (cost=33972852.96..33972852.98 rows=10 width=8)
   Output: match_id
   ->  Sort  (cost=33972852.96..35261659.79 rows=515522734 width=8)
         Output: match_id
         Sort Key: matches_tb1.match_id DESC
         ->  Foreign Scan on public.matches_tb1  (cost=100.00..22832592.02 rows=515522734 width=8)
               Output: match_id
               Remote SQL: SELECT match_id FROM public.matches_tb1
(8 rows)

1 Ответ

0 голосов
/ 12 октября 2018

Для первого запроса в вашем вопросе:

select * from matches_tb1 order by match_id desc limit 10;

По плану EXPLAIN выясняется, что Postgres не использует индекс match_id B-дерева.Это приводит к очень длинному запросу, потому что базе данных приходится сканировать всю таблицу с 500 миллионами записей и сортировать, чтобы найти 10 записей.Что касается , почему Postgres не может использовать индекс, проблема в select *.Когда база данных достигает конечного узла каждой записи в индексе, она находит только значение для match_id.Однако, поскольку вы делаете select *, базе данных придется выполнить поиск в кластеризованном индексе, чтобы найти значения для всех остальных столбцов.Если ваша таблица имеет низкую корреляцию, то оптимизатор, скорее всего, решит полностью отказаться от индекса и просто выполнить полное сканирование таблицы.

Для сравнения рассмотрим один из ваших других запросов, который выполняется быстро:

select match_id from matches_tb1 where match_id > 4164287140
order by match_id desc limit 10

В этом случае можно использовать индекс match_id , поскольку вы выбираете только match_id.Кроме того, ограничение в предложении where помогает еще больше сделать индекс более конкретным.

Таким образом, решение вашей проблемы здесь состоит в том, чтобы не делать select * с limit, если вы хотитезапрос, чтобы закончить быстро.Например, если вы хотите, чтобы в вашей таблице были только два столбца col1 и col2, вы можете добавить эти столбцы в индекс, чтобы покрыть их.Тогда следующий запрос также должен быть быстрым:

select match_id, col1, col2 from matches_tb1 order by match_id desc limit 10;
...