Багатокольоровий індекс та продуктивність


31

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

Сценарій:

  • PostgreSQL 8.4, таблиця з близько мільйона рядків

  • Значення стовпця c1 можуть мати приблизно 100 різних значень . Ми можемо вважати, що значення розподіляються рівномірно, тому у нас є приблизно 10000 рядків для кожного можливого значення.

  • Стовпець c2 може мати 1000 різних значень . У нас є 1000 рядків для кожного можливого значення.

Під час пошуку даних умова завжди включає значення для цих двох стовпців, тому таблиця має індекс багатокольонових, що поєднує c1 і c2. Я читав про важливість правильного впорядкування стовпців у багатоколоночному індексі, якщо у вас є запити, використовуючи лише один стовпець для фільтрації. У нашому сценарії це не так.

Моє запитання таке:

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

введіть тут опис зображення

Зображення, взяті з посилання на статтю про багатоколонові індекси .

Запити використовують значення з двох стовпців для фільтрації. У мене немає запитів, які використовують лише один стовпець для фільтрації. Всі вони є WHERE c1=@ParameterA AND c2=@ParameterB. Також є такі умови:WHERE c1 = "abc" AND c2 LIKE "ab%"

Відповіді:


36

Відповідь

Оскільки ви посилаєтесь на веб-сайт use-the-index-luke.com, врахуйте розділ:

Використовуйте індекс, Лука ›пункт де“ ›пошук діапазонів› більший, менший та між

У ній є приклад, який ідеально відповідає вашій ситуації (індекс з двома стовпцями, один перевіряється на рівність , другий на діапазон ), пояснює (з більшою кількістю тих приємних графічних покажчиків), чому поради @ ypercube є точними і підсумовують його:

Rule of thumb: index for equality first  then for ranges.

Також добре лише для одного стовпчика?

Що робити для запитів лише в одному стовпчику, здається, зрозуміло. Більш детальна інформація та орієнтири, що стосуються цього під цим пов'язаним питанням:

Менш вибіркове стовпчик спочатку?

Крім того, що робити, якщо у вас є лише умови рівності для обох стовпців ?

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

Розгляньте цю демонстрацію або відтворіть її самостійно. Я створюю просту таблицю з двох стовпців зі 100k рядками. Один з дуже малою , другий з великою кількістю чітких значень:

CREATE TEMP TABLE t AS
SELECT (random() * 10000)::int AS lots
     , (random() * 4)::int     AS few
FROM generate_series (1, 100000);

DELETE FROM t WHERE random() > 0.9;  -- create some dead tuples, more "real-life"

ANALYZE t;

SELECT count(distinct lots)   -- 9999
     , count(distinct few)    --    5
FROM   t;

Запит:

SELECT *
FROM   t
WHERE  lots = 2345
AND    few = 2;

EXPLAIN ANALYZE вихід (Кращий з 10 для виключення ефектів кешування):

Послідовне сканування на t (вартість = 0,00..5840,84 рядка = 2 ширина = 8)
               (фактичний час = 5.646..15.535 рядків = 2 петлі = 1)
  Фільтр: ((партії = 2345) І (кілька = 2))
  Буфери: локальний удар = 443
Загальна тривалість виконання: 15.557 мс

Додати індекс, повторно перевірити:

CREATE INDEX t_lf_idx ON t(lots, few);
Сканування покажчика за допомогою t_lf_idx на t (вартість = 0,00..3,76 рядків = 2 ширина = 8)
                                (фактичний час = 0,008..0,011 рядків = 2 петлі = 1)
  Індекс Cond: ((партії = 2345) AND (кілька = 2))
  Буфери: локальний удар = 4
Загальний час виконання: 0,027 мс

Додайте інший індекс, перевірте:

DROP INDEX t_lf_idx;
CREATE INDEX t_fl_idx  ON t(few, lots);
Сканування покажчика за допомогою t_fl_idx на t (вартість = 0,00..3,74 рядки = 2 ширина = 8)
                                (фактичний час = 0,007..0,011 рядків = 2 петлі = 1)
  Індекс Cond: ((кілька = 2) AND (партії = 2345))
  Буфери: локальний удар = 4
Загальний час виконання: 0,027 мс

Це також стосується 3 (або більше) стовпців в індексі?
гайд

@hayd: Не впевнений, на що йдеться "це". Ви можете задати нове запитання . Ви завжди можете посилатися на цей контекст. (І киньте тут коментар, щоб посилатися назад.)
Ервін Брандштеттер,

Під цим "я маю на увазі" чи має значення впорядкування визначення індексу, якщо у визначенні індексу більше 2 стовпців "
hayd,

@hayd: Найважливіший момент: індекс btree хороший для запитів з умовами рівності провідних виразів індексу. Порядок серед них переважно не має значення. Багато інших деталей, які не вмістяться в коментарі ...
Ервін Брандштеттер,

Дякую, я спробую написати цілісне запитання та посилання на нього.
гайд

11

Якщо, як ви кажете, запити, що стосуються цих 2 стовпців, - це всі перевірки рівності обох стовпців, наприклад:

WHERE c1=@ParameterA AND c2=@ParameterB

не турбуйся цим. Я сумніваюся, що буде різниця, і якщо вона буде одна, вона буде незначною. Ви завжди можете протестувати, звичайно, зі своїми даними та налаштуваннями вашого сервера. Різні версії СУБД можуть поводитися дещо по-різному щодо оптимізації.

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

Якби я обирав одне з двох замовлень, я б вирішив поставити спочатку менш вибірковий стовпець. Розглянемо таблицю зі стовпцями yearта month. Більш імовірно, що вам потрібна WHERE year = 2000умова чи а, WHERE year BETWEEN 2000 AND 2013чи а WHERE (year, month) BETWEEN (1999, 6) AND (2000, 5).

Запит цього типу WHERE month = 7 GROUP BY yearможе бути впевнений (Знайдіть людей, народжених в липні), але буде рідше. Це, звичайно, залежить від фактичних даних, що зберігаються у вашій таблиці. Виберіть одне замовлення зараз, скажіть, (c1, c2)і ви завжди можете додати інший індекс пізніше (c2, c1).


Оновлення після коментаря ОП:

Також є такі умови: WHERE c1 = 'abc' AND c2 LIKE 'ab%'

Цей тип запиту, якщо точно вказати умову діапазону для c2стовпця і потрібен буде (c1, c2)індекс. Якщо у вас також є запити зворотного типу:

WHERE c2 = 'abc' AND c1 LIKE 'ab%'

тоді було б добре, якби у вас був і (c2, c1)індекс.

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