PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Бърз начин да откриете броя на редовете на таблица в PostgreSQL

Известно е, че преброяването на редове в големи таблици е бавно в PostgreSQL. Моделът MVCC изисква пълен брой живи редове за точен брой. Има заобиколни решения за ускоряване на това драстично ако броятне трябва да са точни както изглежда във вашия случай.

(Не забравяйте, че дори "точно" преброяване е потенциално мъртво при пристигането!)

Точен брой

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

SELECT count(*) AS exact_count FROM myschema.mytable;
Оценка

Изключително бързи :

SELECT reltuples AS estimate FROM pg_class where relname = 'mytable';

Обикновено оценката е много близка. Колко близо зависи от това дали ANALYZE или VACUUM се изпълняват достатъчно - където "достатъчно" се определя от нивото на активност на запис във вашата таблица.

По-безопасна оценка

Горното игнорира възможността за множество таблици с едно и също име в една база данни - в различни схеми. За да отчетете това:

SELECT c.reltuples::bigint AS estimate
FROM   pg_class c
JOIN   pg_namespace n ON n.oid = c.relnamespace
WHERE  c.relname = 'mytable'
AND    n.nspname = 'myschema';

Прехвърлянето към bigint форматира real номер добре, особено за големи бройки.

По-добра оценка

SELECT reltuples::bigint AS estimate
FROM   pg_class
WHERE  oid = 'myschema.mytable'::regclass;

По-бързо, по-просто, по-безопасно, по-елегантно. Вижте ръководството за Типове идентификатори на обекти.

Заменете 'myschema.mytable'::regclass с to_regclass('myschema.mytable') в Postgres 9.4+, за да не получите нищо вместо изключение за невалидни имена на таблици. Вижте:

  • Как да проверите дали таблица съществува в дадена схема

Още по-добра оценка (за много малко добавени разходи)

Можем да правим това, което прави планерът на Postgres. Цитиране на Примерите за оценка на редове в ръководството:

Тези номера са актуални към последния VACUUM или ANALYZE на масата. След това плановникът извлича действителния текущ брой страници в таблицата (това е евтина операция, която не изисква сканиране на таблицата). Ако това е различно от relpages след това reltuples се мащабира съответно, за да се стигне до текуща оценка на броя на редовете.

Postgres използва estimate_rel_size дефиниран в src/backend/utils/adt/plancat.c , който също покрива ъгъла на липса на данни в pg_class защото връзката никога не е била вакуумирана. Можем да направим нещо подобно в SQL:

Минимална форма

SELECT (reltuples / relpages * (pg_relation_size(oid) / 8192))::bigint
FROM   pg_class
WHERE  oid = 'mytable'::regclass;  -- your table here

Безопасно и ясно

SELECT (CASE WHEN c.reltuples < 0 THEN NULL       -- never vacuumed
             WHEN c.relpages = 0 THEN float8 '0'  -- empty table
             ELSE c.reltuples / c.relpages END
      * (pg_relation_size(c.oid) / pg_catalog.current_setting('block_size')::int)
       )::bigint
FROM   pg_class c
WHERE  c.oid = 'myschema.mytable'::regclass;      -- schema-qualified table here

Не се прекъсва с празни таблици и таблици, които никога не са виждали VACUUM или ANALYZE . Ръководството за pg_class :

Ако таблицата никога не е била вакуумирана или анализирана, reltuples съдържа -1 което показва, че броят на редовете е неизвестен.

Ако тази заявка върне NULL , стартирайте ANALYZE или VACUUM за масата и повторете. (Алтернативно можете да оцените ширината на реда въз основа на типове колони, както прави Postgres, но това е досадно и податливо на грешки.)

Ако тази заявка върне 0 , масата изглежда е празна. Но бих ANALYZE да се уверите. (И може би проверете вашия autovacuum настройки.)

Обикновено block_size е 8192. current_setting('block_size')::int обхваща редки изключения.

Квалификациите на таблицата и схемата го правят имунизиран срещу всеки search_path и обхват.

Така или иначе, заявката постоянно отнема <0,1 ms за мен.

Още уеб ресурси:

  • ЧЗВ за Postgres Wiki
  • Уики страниците на Postgres за прогнози за броя и ефективността на count(*)

TABLESAMPLE SYSTEM (n) в Postgres 9.5+

SELECT 100 * count(*) AS estimate FROM mytable TABLESAMPLE SYSTEM (1);

Както коментира @a_horse, добавената клауза за SELECT командата може да бъде полезна, ако статистиката в pg_class не са достатъчно актуални по някаква причина. Например:

  • Без autovacuum бягане.
  • Непосредствено след голям INSERT / UPDATE / DELETE .
  • TEMPORARY таблици (които не са обхванати от autovacuum ).

Това разглежда само произволно n % (1 в примера) избор на блокове и преброяване на редове в него. По-голяма извадка увеличава цената и намалява грешката, вашият избор. Точността зависи от повече фактори:

  • Разпределение на размера на редовете. Ако даден блок съдържа по-широки от обичайните редове, броят е по-нисък от обикновено и т.н.
  • Мъртви кортежи или FILLFACTOR заемат място на блок. Ако е разпределено неравномерно в таблицата, прогнозата може да е неправилна.
  • Общи грешки при закръгляването.

Обикновено оценката от pg_class ще бъде по-бързо и по-точно.

Отговор на действителен въпрос

Първо, трябва да знам броя на редовете в тази таблица, ако общият брой е по-голям от някаква предварително дефинирана константа,

И дали е...

... е възможно в момента, в който броят мине постоянната ми стойност, той ще спре броенето (и няма да чака да завърши броенето, за да информира, че броят на редовете е по-голям).

Да Можете да използвате подзаявка с LIMIT :

SELECT count(*) FROM (SELECT 1 FROM token LIMIT 500000) t;

Postgres всъщност спира да брои над дадената граница, получавате точна и актуална броят до n редове (500 000 в примера) и n в противен случай. Не толкова бързо, колкото оценката в pg_class , все пак.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Използване на криптиране за засилване на сигурността на базата данни на PostgreSQL

  2. Как да коригирам ГРЕШКА:колона c.relhasoids не съществува в Postgres?

  3. Приоритет, базиран на времето в заявка за активен запис

  4. Хибернация:Създаване на индекс

  5. Превърнете представянето на датата в postgres в низ по ISO 8601