CREATE TABLE personal_data ( id SERIAL PRIMARY KEY , name TEXT NOT NULL , surname TEXT NOT NULL , patronymic TEXT NULL , inn TEXT NULL ); CREATE FUNCTION get_subject_key(name TEXT, surname TEXT, patronymic TEXT) RETURNS TEXT LANGUAGE SQL IMMUTABLE RETURN concat(name, surname, patronymic) ; CREATE INDEX subject_fuzzy_search_idx ON personal_data USING GIST ( get_subject_key(name, surname, patronymic) gist_trgm_ops ) ; EXPLAIN ANALYSE SELECT name, surname, get_subject_key(name, surname, patronymic) <-> get_subject_key('linu', 'storvalds', 'benedct') as dist FROM personal_data ORDER BY dist LIMIT 3; Limit (cost=0.41..1.61 rows=3 width=33) (actual time=6914.946..6915.083 rows=3 loops=1) -> Index Scan using subject_fuzzy_search_idx on personal_data (cost=0.41..795520.95 rows=2000002 width=33) (actual time=6914.945..6915.081 rows=3 loops=1) " Order By: (get_subject_key(name, surname, patronymic) <-> 'linustorvaldsbenedct'::text)" Planning Time: 0.215 ms Execution Time: 6936.034 ms