Почему выбор результата занимает много времени в секционированной таблице в postgreSql? - PullRequest
0 голосов
/ 26 мая 2018

У меня есть ежедневная секционированная таблица в postgresql.Он использует cdr_date для разделения.Когда я выбираю простой запрос, это занимает много времени, я не знаю, почему!

это простой sql

EXPLAIN (ANALYZE , BUFFERS )
select * FROM cdr
WHERE cdr_date >= '2018-05-24 11:59:00.937000 +00:00'
  AND cdr_date <= '2018-05-25 23:59:59.937000 +00:00'

, и это приводит к

Append  (cost=0.56..1036393.46 rows=14908437 width=295) (actual time=5019.283..335535.305 rows=15191628 loops=1)
  Buffers: shared hit=252735 read=1443977 written=125'
  ->  Index Scan using ind_cdr_cdr_date on cdr  (cost=0.56..8.58 rows=1 width=286) (actual time=5019.190..5019.190 rows=0 loops=1)'
        Index Cond: ((cdr_date >= ''2018-05-24 11:59:00.937+00''::timestamp with time zone) AND (cdr_date <= ''2018-05-25 23:59:59.937+00''::timestamp with time zone))
        Buffers: shared hit=178464 read=708130 written=125
  ->  Index Scan using ind_cdr_2018_05_24 on cdr_2018_05_24  (cost=0.43..567998.02 rows=7158579 width=295) (actual time=0.091..311773.252 rows=7846816 loops=1)
        Index Cond: ((cdr_date >= ''2018-05-24 11:59:00.937+00''::timestamp with time zone) AND (cdr_date <= ''2018-05-25 23:59:59.937+00''::timestamp with time zone))
        Buffers: shared hit=74264 read=383715
  ->  Seq Scan on cdr_2018_05_25  (cost=0.00..468386.85 rows=7749857 width=295) (actual time=5.192..16189.737 rows=7344812 loops=1)
        Filter: ((cdr_date >= ''2018-05-24 11:59:00.937+00''::timestamp with time zone) AND (cdr_date <= ''2018-05-25 23:59:59.937+00''::timestamp with time zone))
        Buffers: shared hit=7 read=352132
Planning time: 3.394 ms
Execution time: 336984.703 ms

здесьмоя корневая таблица

CREATE TABLE cdr
(
  id                      BIGSERIAL                NOT NULL
    CONSTRAINT cdr_pkey
    PRIMARY KEY,
  username                VARCHAR(256)             NOT NULL,
  user_id                 BIGINT,
  cdr_date                TIMESTAMP WITH TIME ZONE NOT NULL,
  created_at              TIMESTAMP WITH TIME ZONE NOT NULL,
  last_reset_time         TIMESTAMP WITH TIME ZONE,
  prev_cdr_date           TIMESTAMP WITH TIME ZONE NOT NULL
);

CREATE INDEX ind_cdr_user_id
  ON cdr (user_id);

CREATE INDEX ind_cdr_cdr_date
  ON cdr (cdr_date);

а вот моя дочерняя таблица

-- auto-generated definition
CREATE TABLE cdr_2018_05_25
(
  CONSTRAINT cdr_2018_05_25_cdr_date_check
  CHECK ((cdr_date >= '2018-05-25 00:00:00+00' :: TIMESTAMP WITH TIME ZONE) AND
         (cdr_date <= '2018-05-26 00:23:29.064408+00' :: TIMESTAMP WITH TIME ZONE))
)
  INHERITS (cdr);

CREATE INDEX ind_cdr_2018_05_25_user_id
  ON cdr_2018_05_25 (user_id);

CREATE INDEX ind_cdr_2018_05_25
  ON cdr_2018_05_25 (cdr_date);

Ответы [ 2 ]

0 голосов
/ 26 мая 2018

Нет никакого способа, которым должно потребоваться 5 секунд, чтобы найти 0 строк при сканировании индекса корневой таблицы.Я бы сказал, что ваша корневая таблица (или индексы, в любом случае) сильно раздута.И если это так, может быть, ваши другие тоже.Достаточно ли вы пылесосите эти столы или даже вообще?Посмотрите в pg_stat_user_tables последний раз, когда их пылесосили, либо вручную, либо автоматически.

0 голосов
/ 26 мая 2018

Поскольку ваш раздел большой, и вы в основном выбираете большую часть данных в разделе.

Фильтр не равен проверке, поэтому после определения того, какой раздел использовать, он все равно сканируетиндекс.

Я могу предложить 3 решения, которые могут работать вместе:

  1. Не разбивать на диапазоны с таким высоким разрешением.Попробуйте добавить еще одно поле, которое является просто компонентом DATE, и вместо этого используйте проверку с оператором равенства.Это также гарантирует, что ваши разделы не перекрываются, как в этом случае.Это не очень поможет в этом конкретном случае, если вы действительно не хотите выбирать все данные из одного раздела.
  2. Cluster таблица индекса cdr_date, которая будетрезко ускорить такие запросы.

    CLUSTER cdr_2018_05_24 USING ind_cdr_2018_05_24
    
  3. Рассмотрите возможность разбиения разделов по часам, если вы часто выбираете меньшие временные диапазоны.Для такого запроса достаточно 7 миллионов строк.

...