У меня есть функция pl-pgsql для поиска информации о гео-IP для нескольких адресов. Это в основном делает цикл в списке адресов и ищет один за другим. Я ожидаю, что время выполнения будет похоже на общее время выполнения, при котором вручную выполняется поиск IP-адресов без функции. Но это оказывается намного медленнее. Почему?
Я пытался проверить с двумя IP-адресами 27.111.12.93
и 52.23.111.175
. И я также записал / выбрал время выполнения для каждого цикла в функции. С другой стороны, я также запускал вручную для каждого из двух IP-адресов с почти одинаковым SQL и проверял время выполнения с помощью explain analyze
. Я подозревал, что кеш влияет, поэтому я протестировал несколько раз для обоих, предположим, что коэффициент кеша должен одинаково повлиять на обе стороны. (Кстати, тип данных ipaddress относится к расширению Postgres ip4r.)
Код функции находится здесь:
CREATE OR REPLACE FUNCTION test(ips ipaddress[])
RETURNS TABLE(
latitude character varying(16),
longitude character varying(16),
country_name character varying(60),
subdivision_1_iso_code character varying(4),
city_name character varying(100),
ip ipaddress,
ts interval
) AS $$
DECLARE ip ipaddress;
tstamp timestamptz;
BEGIN
FOR ip IN SELECT DISTINCT ips_t.ip FROM (SELECT unnest(ips) ip) ips_t
LOOP
tstamp := clock_timestamp();
RETURN QUERY
SELECT b.latitude, b.longitude, l.country_name, l.subdivision_1_iso_code, l.city_name, ip, clock_timestamp() - tstamp
FROM blocks4 b
INNER JOIN locations l USING (geoname_id)
WHERE b.network >>= ip
LIMIT 1;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql STABLE STRICT;
И я вызываю его так:
select * from test(
ARRAY['27.111.12.93'::ipaddress, '52.23.111.175'::ipaddress]
);
Тогда код для проверки каждого IP-адреса вручную выглядит следующим образом:
SELECT b.latitude, b.longitude, l.country_name, l.subdivision_1_iso_code, l.city_name, '27.111.12.93'::ipaddress, clock_timestamp()
FROM blocks4 b
INNER JOIN locations l USING (geoname_id)
WHERE b.network >>= '27.111.12.93'::ipaddress
LIMIT 1;
Результат выполнения функции:
latitude | longitude | country_name | subdivision_1_iso_code | city_name | ip | ts
----------+-----------+---------------+------------------------+-----------+---------------+-----------------
-41.0000 | 174.0000 | New Zealand | | | 27.111.12.93 | 00:00:00.46761
39.0481 | -77.4728 | United States | VA | Ashburn | 52.23.111.175 | 00:00:00.485468
(2 rows)
Как видите, время выполнения для каждогоIP-адрес превышает 400 мс.
Затем проверяйте их вручную по одному, время запроса для IP 27.111.12.93
равно
Planning Time: 0.213 ms
Execution Time: 34.718 ms
и для 52.23.111.175:
Planning Time: 0.217 ms
Execution Time: 91.154 ms
Почему время выполнения функции намного дольше, если учесть, что они в основном делают одно и то же?