Почему результат подсчета отличается от обычного числа строк выбора? в Авроре Postgresql - PullRequest
2 голосов
/ 03 октября 2019

Я использую Postgresql от Aurora. Количество запросов на нормальное количество не соответствует количеству строк при поиске записей со звездочкой. В чем причина?

Рассматриваемая система использует AWS Aurora и версию Postgresql 9.6.8 в качестве движка. Как показано ниже, обычные результаты поиска для Postgresql и результаты подсчета не совпадают.

нормальный поиск
SELECT * FROM samples WHERE date BETWEEN '2019-09-25 00:00:00' AND '2019-09-26 00:00:00';

В результате возвращается 17613 записей.

запрос количества
SELECT COUNT(*) FROM samples WHERE date BETWEEN '2019-09-25 00:00:00' AND '2019-09-26 00:00:00';

17875возвращается как запрос подсчета.

Эта таблица имеет несколько первичных ключей и несколько столбцов, которые допускают пустые значения. Почему количество результатов отличается между SELECT * и SELECT COUNT(*)?

Кстати, если вы укажете имя таблицы или первичный ключ, оно совпадет с количеством записей в обычном поиске.

SELECT COUNT(sample_id) FROM samples WHERE date BETWEEN '2019-09-25 00:00:00' AND '2019-09-26 00:00:00';

или

SELECT COUNT(samples) FROM samples WHERE date BETWEEN '2019-09-25 00:00:00' AND '2019-09-26 00:00:00';

17613 возвращается как запрос подсчета.

Я заплачу, потому что моя работа не работает. Спасибо.

Ответы [ 2 ]

0 голосов
/ 04 октября 2019

Я не знаю причину, но выяснилось, что это произошло, когда было выполнено сканирование только по индексу на реплике чтения Aurora Postgres.

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

SELECT *
testdb=> explain analyse select * from samples where date between '2019-09-25 00:00:00' and '2019-09-26 00:00:00';
                                                                 QUERY PLAN                                                                 
--------------------------------------------------------------------------------------------------------------------------------------------
 Index Scan using idx_samples on samples  (cost=0.43..5852.48 rows=3906 width=627) (actual time=0.014..18.325 rows=17613 loops=1)
   Index Cond: ((date >= '2019-09-25'::date) AND (date <= '2019-09-26'::date))
 Planning time: 1.154 ms
 Execution time: 18.969 ms
(4 rows)

В этом случае для получения данных в виде записи выбирается не только индекс, но и фактические данные. В результате этого могут быть возвращены 17613 строк.

SELECT COUNT(*)
testdb=> explain analyse select count(*) from samples where date between '2019-09-25 00:00:00' and '2019-09-26 00:00:00';
                                                                             QUERY PLAN                                                                     
----------------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=200.32..200.33 rows=1 width=8) (actual time=19.971..19.972 rows=1 loops=1)
   ->  Index Only Scan using idx_samples on samples  (cost=0.43..190.56 rows=3906 width=0) (actual time=0.022..18.901 rows=17875 loops=1)
         Index Cond: ((date >= '2019-09-25'::date) AND (date <= '2019-09-26'::date))
         Heap Fetches: 59983
 Planning time: 1.125 ms
 Execution time: 19.994 ms
(6 rows)

Однако если при подсчете получено только количество записей, столбец даты, добавленный в условие, является целью индекса, поэтому Index Only Scan используется. В результате 17875 строк имеют право на возврат.

Это не происходит с мастерами Aurora, только с репликами чтения.

Я много искал и не могу найтистатья о первопричине возникновения ненужных кортежей или о том, что вакуум не сделан. Я также искал форумы Aurora и Postgresql, но не смог найти такую ​​статью. Инженер, работающий со мной над этим событием, не мог скрыть удивления.

Я думаю, что количество фактических данных - это правильный ответ, а не результат сканирования только по индексу. Как решение, я собираюсьпроверить количество столбцов, которые не проиндексированы счетчиком, например SELECT COUNT (sample_id).

Было бы полезно, если бы кто-то поделился статьей о причине этого события или о том, что это была такая спецификация.

0 голосов
/ 03 октября 2019

Функция count(<column_name>) возвращает количество ненулевых значений. count(*) возвращает общее количество значений NULL и не NULL.

...