Я пришел из Mysql и не sql базы данных, и я новичок в Postgress db. Я использую Postgres 11,6 на Авроре AWS.
Я пытаюсь создать таблицы, состоящие из двух столбцов, ключа и значения jsonb.
Каждое значение выглядит следующим образом:
{"game": "game6",
"username": "Djobi",
(bunch of fields)
"permissions": ["permission3", "permission1", "permission5"]}
Я пытаюсь добавить разные индексы, чтобы увидеть, каковы возможности БД. Один из них, это найти пользователя по имени. Другой способ - найти пользователей с указанным разрешением c.
account_index | account_index_username | CREATE INDEX account_index_username ON public.account_index USING btree (((value -> 'username'::text)))
account_index | account_index_permissions | CREATE INDEX account_index_permissions ON public.account_index USING gin (((value -> 'permissions'::text)))
account_index | account_global_gin | CREATE INDEX accountgin ON public.account_index USING gin (value)
У меня есть две таблицы с точно такими же данными. Каждая таблица имеет около 30 миллионов строк. Один с индексом, один без. Я выполняю следующие запросы для проверки производительности:
SELECT 1
FROM account_noindex
WHERE value @> '{"permissions": ["permission1"]}' limit 10;
Я пытаюсь найти пользователя, имеющего разрешение1. (примечание: пока не уверен, как спросить, как получить конкретное разрешение1 по сравнению с любым разрешением, включая разрешение1). При выполнении моего запроса в моих индексных таблицах я получаю время ответа 5000 мс. При выполнении моего запроса в моих неиндексных таблицах время ответа составляет 50 мс.
Таким образом, неиндексная таблица в 100 раз быстрее индексной, что, я должен сказать, смущает меня. Если я попытаюсь выполнить объяснение двух запросов, я получу следующие результаты:
Таблица индексов:
Limit (cost=430.49..468.31 rows=10 width=32)
-> Bitmap Heap Scan on account_index (cost=430.49..144146.44 rows=37999 width=32)
Recheck Cond: (value @> '{"permissions": ["permission1"]}'::jsonb)
-> Bitmap Index Scan on accountgin (cost=0.00..420.99 rows=37999 width=0)
Index Cond: (value @> '{"permissions": ["permission1"]}'::jsonb)
(5 rows)
Таблица не индексов
Limit (cost=0.00..1935.23 rows=10 width=4)
-> Seq Scan on account_noindex (cost=0.00..7360637.42 rows=38035 width=4)
Filter: (value @> '{"permissions": ["permission1"]}'::jsonb)
Если я попытаюсь на go глубже в смещении (выше 100k) разница менее очевидна, но неиндексная таблица все еще быстрее.
[править] Здесь полный буфер анализа для индексированной таблицы:
EXPLAIN (ANALYZE, BUFFERS) SELECT value->'permissions' FROM account_index WHERE value @> '{"permissions": ["permission1"]}' limit 12;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=430.49..475.88 rows=12 width=32) (actual time=1926.289..1926.365 rows=12 loops=1)
Buffers: shared hit=24398
-> Bitmap Heap Scan on account_index (cost=430.49..144146.44 rows=37999 width=32) (actual time=1926.287..1926.361 rows=12 loops=1)
Recheck Cond: (value @> '{"permissions": ["permission1"]}'::jsonb)
Rows Removed by Index Recheck: 30
Heap Blocks: lossy=8
Buffers: shared hit=24398
-> Bitmap Index Scan on accountgin (cost=0.00..420.99 rows=37999 width=0) (actual time=1916.655..1916.656 rows=8386144 loops=1)
Index Cond: (value @> '{"permissions": ["permission1"]}'::jsonb)
Buffers: shared hit=24390
Planning Time: 0.073 ms
Execution Time: 1927.143 ms
Так чего мне здесь не хватает? Я неправильно создал свой индекс GIN? Или я неправильно выполняю запрос?
Обратите внимание, что у меня та же проблема с индексом в моем имени пользователя. Когда я делаю запрос на поиск пользователя с указанным c именем пользователя без какого-либо LIMIT, я получаю полное сканирование таблицы с индексом GIN или без него. Когда я добавляю индекс BTREE, тогда не возникает никаких проблем и не требуется никаких ограничений.