Как повысить производительность SQL-запроса COUNT в PostgreSQL? - PullRequest
0 голосов
/ 19 октября 2019

У меня есть таблица с множителями столбцов. Но для простоты мы можем рассмотреть следующую таблицу:

create table tmp_table
(
    entity_1_id varchar(255) not null,
    status integer default 1 not null,
    entity_2_id varchar(255)
);

create index tmp_table_entity_1_id_idx
    on tmp_table (entity_1_id);

create index tmp_table_entity_2_id_idx
    on tmp_table (entity_2_id);

Я хочу выполнить этот запрос:

SELECT tmp_table.entity_2_id, COUNT(*) FROM tmp_table 
    WHERE tmp_table.entity_1_id='cedca236-3f27-4db3-876c-a6c159f4d15e' AND 
          tmp_table.status <> 2 AND 
          tmp_table.entity_2_id = ANY (string_to_array('21c5598b-0620-4a8c-b6fd-a4bfee024254,af0f9cb9-da47-4f6b-a3c4-218b901842f7', ',')) 
    GROUP BY tmp_table.entity_2_id;

Это прекрасно работает, когда я отправляю строку в функцию string_to_arrayс несколькими значениями (например, 1-20). Но когда я пытаюсь отправить 500 элементов, это работает слишком медленно. К сожалению, мне действительно нужно 100-500 элементов.

1 Ответ

1 голос
/ 19 октября 2019

Для этого запроса:

SELECT t.entity_2_id, COUNT(*)
FROM tmp_table t
WHERE t.entity_1_id = 'cedca236-3f27-4db3-876c-a6c159f4d15e' AND 
      t.status <> 2 AND 
      t.entity_2_id = ANY (string_to_array('21c5598b-0620-4a8c-b6fd-a4bfee024254,af0f9cb9-da47-4f6b-a3c4-218b901842f7', ',')) 
GROUP BY t.entity_2_id;

Я бы порекомендовал индекс для tmp_table(entity_1_id, entity_2_id, status).

Однако вы можете найти это быстрее:

select rst.entity_2_id,
       (select count(*)
        from tmp_table t
        where t.entity_2_id = rst.entity_2_id and
              t.entity_1_id = 'cedca236-3f27-4db3-876c-a6c159f4d15e' AND 
              t.status <> 2
       ) as cnt
from regexp_split_to_table(str, ',') rst(entity_2_id);

Тогдавам нужен индекс для tmp_table(entity_2_id, entity_1_id, status).

В большинстве баз данных это будет быстрее, поскольку индекс является индексом покрытия, и это позволяет избежать окончательного агрегирования по всему набору результатов. Однако Postgres хранит информацию о блокировке на страницах данных, поэтому их все равно необходимо прочитать. Это все еще стоит попробовать.

...