Я использую Postgres для хранения большого количества транзакций и пытаюсь сохранить время чтения для определенного оператора Select в десятках миллисекунд.
Схема таблицы A (> 100-миллиметровые строки): (userID int, itemID int). Индексируется по идентификатору пользователя
Схема таблицы B (строки 1 мм): (categoryID int, itemID int). Индексируется по категории ID. Количество категорий = 500, и каждый itemID принадлежит только одной категории.
Запрос, который я хочу оптимизировать, для выполнения которого в настоящий момент у меня уходит ~ 100 мс:
select * from TableA
where userID = x and itemID in
(select itemID from TableB
where categoryID = y)
Простым способом решения этой проблемы было бы создание денормализованной таблицы с userID, itemID и categoryID в качестве столбцов и индексацией (userID, categoryID). Однако сопоставление categoryID -> itemID может измениться, поэтому я хотел избежать полного сканирования таблицы и обновлять строки каждый раз, когда это происходит.
Существуют ли другие методы / методы индексации для ускорения этой операции JOIN? Любые альтернативные способы размещения данных также приветствуются. Спасибо!
Редактировать: добавление примера плана запроса.
[(' -> Hash Semi Join (cost=159.50..382.67 rows=164 width=50)'),
(' Hash Cond: (tableA.itemId = tableB.itemId)'),
(' -> Index Scan using userId on tableA (cost=0.57..208.31 rows=5185 width=50)'),
(' Index Cond: (userId = 4000)'),
(' -> Hash (cost=117.05..117.05 rows=3350 width=4)'),
(' Buckets: 4096 Batches: 1 Memory Usage: 161kB',),
(' -> Index Scan using categoryId on tableB (cost=0.42..117.05 rows=3350 width=4)'),
(' Index Cond: (categoryId = 1002)',), ('Planning time: 0.149 ms',)]