Чи небезпечний REINDEX?


17

Я намагався COUNT(*)створити таблицю з 150 000 рядків, в якій є Первинний ключ. Це інструмент близько 5 хвилин, тому я зрозумів, що це проблема індексації.

Посилаючись на посібник з PostgreSQL :

REINDEX подібний до краплі та відтворення індексу тим, що вміст індексу перебудовується з нуля. Однак міркування щодо блокування досить різні. REINDEX блокує записи, але не зчитує батьківську таблицю індексу. Він також займає ексклюзивне блокування певного оброблюваного індексу, який блокує зчитування, які намагаються використовувати цей індекс (...) Наступний CREATE INDEX блокує запису, але не зчитування; оскільки індекс відсутній, жодне читання не намагатиметься його використовувати, це означає, що блокування не буде, але читання можуть бути примушені до дорогих послідовних сканувань.

З власного досвіду ви можете сказати:

  • є REINDEXING небезпечно? Чи може це завдати шкоди послідовності даних?
  • Чи може це зайняти багато часу?
  • Це ймовірне рішення мого сценарію?

Оновлення:

Рішення, яке працювало для нас, було відтворення того ж індексу з іншою назвою, а потім видалення старого індексу.

Створення індексу відбувається дуже швидко, і ми зменшили розмір індексу з 650 МБ до 8 МБ. Використання COUNT(*)з betweenзаймає всього 3 секунди.

Відповіді:


15

Повторне дексидування не є небезпечним і не може зашкодити послідовності даних. Однак якщо у вас є час критичного запису, ви можете втратити дані, якщо таблиця заблокована і DML перервано.

Повторне дексирування не повинно зайняти багато часу, але, як правило, передбачає читання всієї таблиці, сортування полів індексу та написання нового індексу. Враховуючи час на COUNT(*)це, ймовірно, знадобиться п'ять хвилин і більше.

Навряд чи це проблема індексації. COUNT(*)слід використовувати сканування таблиці, в цьому випадку не зчитується індекс. Я б очікував, що у вас є якась проблема IO.

Спробуйте використовувати COUNT(1) або COUNT(pk_field)який може використовувати індекс.

Якщо ви працюєте на платформі Unix або Linux, ви, можливо, захочете контролювати активність диска sar . Можливо, у вас також є несправний диск, який може різко знизити коефіцієнти вводу-виводу.

Таблиці з великими об'єктами також можуть значно збільшити IO для побудови записів для COUNT (*).


2
Як повідомляє wiki.postgresql.org, COUNT(*)це найкращий вибір:If you are using count(*), the database is free to use any column to count, which means it can pick the smallest covering index to scan (note that this is why count(*) is much better than count(some_field), as long as you don't care if null values of some_field are counted). Since indexes often fit entirely in memory, this means count(*) is often very fast.
orange80

1

Я не впевнений у найкращій відповіді для вас. Однак, схоже, ця тема пропонує хороші пропозиції: n http://postgresql.1045698.n5.nabble.com/count-performance-issue-td2067873.html

Одне зауваження полягає в тому, що ви можете застосувати TRIGGER для підтримки кількості рядків в окремій таблиці (якщо COUNT (*) вашими програмами часто називатиметься).

Деякі відповіді говорять про те, що це є симптоматикою бази даних, що не була досить вакуумована останнім часом (припускаючи, що на вашому сервері або на цій базі даних зокрема, автовакуум вимкнено)?

Ще одна пропозиція виглядає так:

ANALYZE tablename;
SELECT reltuple FROM pg_class WHERE relname = 'tablename';

І хтось, ідентифікований як А. Кречмер, зазначає:

Ні. Поточна реалізація індексу не містить інформації про видимість рядків у поточній транзакції. Вам потрібно просканувати всю таблицю даних, щоб отримати, чи видно поточний рядок у межах поточної транзакції.

... підтримуючи мій коментар щодо дозволів на рівні рядків, що викликають занепокоєння щодо ефективності.

Мій пошук також виявив WikiVS: MySQL проти PostgreSQL: COUNT (*) .

Ви можете ознайомитись з іншими результатами, які я знайшов, використовуючи продуктивність Google: postgresql count (*)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.