Я использую сервер базы данных, который содержит большую таблицу бизнес-адресов. К нему подключено приложение, которое принимает пользовательские координаты и тип бизнеса, который они ищут, и возвращает бизнес, ближайший к этому пользователю.
Первоначально мое приложение использовало простую инструкцию SELECT для поиска ближайшего предприятия, возвращается таблица всех названий предприятий и выполняется некоторая сортировка на конце приложения (это где данные о координатах пользователя и адреса). используется), чтобы найти ближайший к ним:
Select * from my_table where business_type = 'bakeries';
Это не показалось мне идеальным, так как на конце приложений было заметное отставание в полсекунды, когда он сортировал данные, чтобы найти ближайший. В настоящее время я изучаю, могут ли все вычисления выполняться быстрее в конце базы данных. Таким образом, я узнал о POSTGIS и его функциях, чтобы найти координаты, наиболее близкие к входу. Используя его функциональность, я придумал этот запрос, который будет выполняться для каждого пользовательского запроса:
SELECT *, ST_Distance(ST_GeogFromText('SRID=4326;POINT(user_long user_lat)'), geom, false) as
distance from my_table where business_type = 'Insurance' order by distance limit 1;
Это, кажется, намного более быстрый ответ, особенно для типов бизнеса, у которых есть много списков в таблице (таких как Страховые компании). Тем не менее, я замечаю, что он ужасно масштабируется, когда я пытаюсь провести стресс-тестирование поступающих запросов. 500 одновременных запросов к URL-адресу быстро приводят к тому, что загрузка ЦП базы данных достигает 100%, поэтому этот подход не будет работать в пиковые моменты времени.
"Limit (cost=12804.92 rows=1 width=261)"
" -> Sort (cost=12804.91..12878.92 rows=29602 width=261)"
" Sort Key: (_st_distance('0101000020E61000007AC7293A927F52C0D34D621058614440'::geography, (geom)::geography, '0'::double precision, false))"
" -> Index Scan using business_name_index on my_table (cost=0.43..12656.90 rows=29602 width=261)"
" Index Cond: (business_type = 'Insurance'::text)"
Есть ли способ сделать это гораздо более жизнеспособным, или я должен отказаться от этой идеи и попробовать другой путь? Я знаю одну альтернативу - использовать ST_DWithin
, чтобы найти все ближайшие адреса в определенном радиусе (как показано здесь ), но я не могу определить минимальное расстояние, так как некоторые могут быть слишком далеко для пользователя по умолчанию.