У мене є таблиця з рядками 50K. Це насправді таблиця PostGIS.
Запит складається з 4 частин (1 обов'язкова) (3 необов’язково)
- перетинна коробка (географічний прямокутник) з 4 латом, довгий (я використовую st_intersects) [Обов’язково]
- Діапазон дат (хв., Макс.) У полі дати
- Тип файлу (набір до 8 текстових значень), який зараз використовується IN (.....), але я можу зробити цю таблицю тимчасових, якщо потрібно. Я бачу, що багато людей не люблять IN.
- Країна (текстове значення).
Я очікую приблизно 100 - 4000 повернутих рядків
Якщо я створю складений індекс на таблиці, який стовпець я повинен використовувати спочатку. Дрібнозернисте - це, мабуть, місце (дані поширюються по всьому світу). На даний момент я маю це як індекс GIST.
Інші індекси будуть BTREE.
Моя інтуїція говорить про використання дрібнозернистих і звичайно останніх. Наприклад, існує лише близько 12 типів файлів, так що це буде дуже великі відра для індексу.
Що говорять гуру PostgreSQL та PostGIS (які знають внутрішні системи)?
ОНОВЛЕННЯ:
Дозвольте я загострити це питання.
- Я не хочу, щоб хтось мав виконувати ту роботу, яку я повинен робити. Я занадто багато поважаю твій час. Тож я перейду до аналізу пояснень пізніше.
- Я шукав лише вказівки та поради та рекомендації.
- Я прочитав цю чудову маленьку публікацію: https://devcenter.heroku.com/articles/postgresql-indexes#managing-and-maintain-indexes про індекси
- Зазвичай я створюю 4 окремі індекси (геополе, назва країни, тип файлу та дату), але те, що я хочу бачити, як би складений складений запит.
Скажіть, чи будь-яке з цих припущень невірно. (Я досить новачок в ідеї складних індексів)
- Порядок важливий. Виберіть в якості першого індексу той, який скоротить рядки найбільше (в моєму випадку найкраще буде розташування (географія), який є простим багатокутником або багатокутником).
- Іноді запити пропускають індекси. Але якщо я створять складений запит з ключем (# 1, # 2, # 3, # 4), то навіть якщо користувач створить щось, що запитує №1, №3, планувальник все одно використовуватиме єдиний складений запит, оскільки він замовляє підтримується.
- Зазвичай я створив би три запити BTREE і один GIST (для типу географії). PostGIS не підтримує створення сполуки з декількох типів індексів. Тому мені доведеться використовувати GIST складний індекс. Але це не повинно зашкодити речам.
- Якщо я створюю додаткові індекси складних чи єдиних значень, планувальник досить розумний, щоб вибрати найрозумніший .....
- Назва країни може містити близько 250 різних значень і, очевидно, сильно пов'язана з місцем розташування (геобокс), але якщо наступний найкращий індекс для зменшення розміру рядка - це file_type, я повинен використовувати це наступне. Я не очікую, що користувачі часто використовують країну або дату у своїх наборах запитів.
- Я НЕ повинен турбуватися про те, що створення складного індексу з 4 клавіш значно збільшить розмір даних індексу. Тобто, якщо індекс з одним ключем складе 90% від підвищення продуктивності, не завадить додати ще 3 елементи, щоб зробити його складнішим. І навпаки, мені справді слід створити обидва індекси. Єдиний географічний індекс, а також складений індекс, і нехай планувальник визначить, що найкраще, і він врахує розмір таблиці індексу.
Знову ж таки, я нікого не прошу розробити моє рішення, я не сподіваюся на роботу інших. Але мені потрібні речі, які документація PostGreSQL не говорить мені про реалізацію
[Причиною, поки я не маю показати EXPLAIN результату, є те, що я повинен створити цю таблицю рядків 25K з таблиці 24М рядків. Це займає більше часу, ніж я думав. Я об'єдную речі в 1000 груп елементів і дозволяю користувачеві запитувати проти таблиці рядків 25K. Але наступне моє запитання передбачає використання результатів цього запиту, щоб перейти до таблиці рядків MASTER 25M та витягнути речі, і саме там ефективність складного індексу дійсно буде HIT].
зразок запиту нижче:
SELECT
public.product_list_meta_mv.cntry_name AS country,
public.product_list_meta_mv.product_producer AS producer,
public.product_list_meta_mv.product_name AS prod_name,
public.product_list_meta_mv.product_type AS ptype,
public.product_list_meta_mv.product_size AS size,
ST_AsGeoJSON(public.product_list_meta_mv.the_geom, 10, 2) AS outline
FROM
public.product_list_meta_mv
WHERE
public.product_list_meta_mv.cntry_name = 'Poland'
AND
ST_Intersects(public.product_list_meta_mv.the_geom,
st_geogfromtext('SRID=4326;POLYGON((21.23107910156250 51.41601562500000,
18.64379882812500 51.41601562500000,
18.64379882812500 48.69415283203130,
21.23107910156250 48.69415283203130,
21.23107910156250 51.41601562500000))'))
AND (date >= '1/2/1900 5:00:00 AM'
AND date <= '2/26/2014 10:26:44 PM')
AND (public.product_list_meta_mv.product_type in
('CIB10','DTED0','DTED1','DTED2','CIB01','CIB05')) ;
ПОЯСНІТЬ АНАЛІЗУВАННЯ (я не вкладав жодних складних індексів, і зі швидкістю, яку я бачу, я не знаю, чи потрібно мені).
"Bitmap Heap Scan on catalog_full cat (cost=4.33..37.49 rows=1 width=7428) (actual time=1.147..38.051 rows=35 loops=1)"
" Recheck Cond: ('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography && outline)"
" Filter: (((type)::text = ANY ('{CADRG,CIB10,DTED1,DTED2}'::text[])) AND (_st_distance('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography, outline, 0::double precision, false) < 1e-005::double precision))"
" Rows Removed by Filter: 61"
" -> Bitmap Index Scan on catalog_full_outline_idx (cost=0.00..4.33 rows=8 width=0) (actual time=0.401..0.401 rows=96 loops=1)"
" Index Cond: ('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography && outline)"
"Total runtime: 38.109 ms"
EXPLAIN ANALYZE SELECT pid,product_name,type,country,date,size,cocom,description,egpl_date,ST_AsGeoJSON(outline, 10, 2) AS outline
FROM portal.catalog_full AS cat
WHERE ST_Intersects(st_geogfromtext('SRID=4326;POLYGON((21.2200927734375 51.38031005859375, 18.65478515625 51.38031005859375, 18.65478515625 48.7298583984375, 21.2200927734375 48.7298583984375, 21.2200927734375 51.38031005859375))'), cat.outline)
AND (cat.type in ('CADRG','CIB10','DTED1','DTED2'))
EXPLAIN ANALYZE
для запиту.