Как эффективно выполнить запрос на равенство для данных значения ключа с разрешенными дублирующимися ключами?
У меня следующая ситуация:
Данные = около 400 миллионов (строка1, строка2, оценка) кортежей
Размер данных ~ 20 ГБ, не помещается в памяти.
Данные хранятся в файле в формате csv и не сортируются ни по одному полю.
Мне нужно эффективно получить все кортежи с определенной строкой, например, все кортежи st string1 = 'google'.
Как мне спроектировать систему так, чтобы я мог сделать это эффективно?
Я уже пробовал postgresql с индексом B-дерева и индексом GIN, но они недостаточно быстры (> 20-30 секунд) для запроса.
В идеале мне нужно решение, которое сортирует кортежи по string1, сохраняет их в отсортированном виде, а затем запускает бинарный поиск с последующим последовательным сканированием для поиска. Но я не знаю, какая база данных или система реализует такую функциональность.
ОБНОВЛЕНИЕ: Вот детали postgres:
Я загрузил данные в postgres, используя команду COPY. Затем я создал два индекса для string1, одно b-дерево и один GIN. Однако Postgres не использует ни один из них.
Создать таблицы:
CREATE TABLE mytable(
string1 varchar primary key, string2 varchar, source_id integer REFERENCES sources(id), score real);
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX string1_gin_index ON mytable USING gin (string1 gin_trgm_ops);
CREATE INDEX string1_index ON mytable(lower(string1));
План запроса:
isa=# EXPLAIN ANALYZE VERBOSE select * from mytable where string1 ilike 'google';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on public.mytable (cost=235.88..41872.81 rows=11340 width=29) (actual time=20234.765..25566.128 rows=30971 loops=1)
Output: hyponym, string2, source_id, score
Recheck Cond: ((mytable.string1)::text ~~* 'google'::text)
Rows Removed by Index Recheck: 34573
-> Bitmap Index Scan on string1_gin_index (cost=0.00..233.05 rows=11340 width=0) (actual time=20218.263..20218.263 rows=65544 loops=1)
Index Cond: ((mytable.string1)::text ~~* 'google'::text)
Total runtime: 25568.209 ms
(7 rows)
isa=# EXPLAIN ANALYZE VERBOSE select * from isa where string1 = 'google';
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
Seq Scan on public.mytable (cost=0.00..2546373.30 rows=3425 width=29) (actual time=11692.606..139401.099 rows=30511 loops=1)
Output: string1, string2, source_id, score
Filter: ((mytable.string1)::text = 'google'::text)
Rows Removed by Filter: 124417194
Total runtime: 139403.950 ms
(5 rows)