Не мога да говоря за самия интерфейс на Perl от страна на клиента, но мога да хвърля малко светлина върху страната на сървъра на PostgreSQL.
PostgreSQL има подготвени изрази и неподготвени изрази. Неподготвените отчети се анализират, планират и изпълняват незабавно. Те също не подмяна на параметър за поддръжка. На обикновен psql
shell можете да покажете техния план за заявка по този начин:
tmpdb> explain select * from sometable where flag = true;
От друга страна има подготвени изрази:те обикновено (вижте „изключение“ по-долу) се анализират и планират в една стъпка и се изпълняват във втора стъпка. Те могат да бъдат повторно изпълнени няколко пъти с различни параметри, защото правят подмяна на параметър за поддръжка. Еквивалентът в psql
е това:
tmpdb> prepare foo as select * from sometable where flag = $1;
tmpdb> explain execute foo(true);
Може да видите, че планът е различен от плана в неподготвения израз, тъй като планирането вече е извършено в prepare
фаза, както е описано в документа за PREPARE
:
Това също означава, че планът НЕ оптимизиран за заместените параметри:В първите примери може да се използва индекс за flag
защото PostgreSQL знае, че в рамките на милион записа само десет имат стойност true
. Това разсъждение е невъзможно, когато PostgreSQL използва подготвен израз. В този случай се създава план, който ще работи възможно най-добре за всички възможни стойности на параметри. Това може изключете споменатия индекс, тъй като извличането на по-добрата част от пълната таблица чрез произволен достъп (поради индекса) е по-бавно от обикновеното последователно сканиране. PREPARE
doc потвърждава това:
Между другото – Относно кеширането на плана PREPARE doc също има какво да каже:
Освен това няма автоматично кеширане на план и няма кеширане/повторно използване при множество връзки.
ИЗКЛЮЧЕНИЕ :Споменах "обикновено". Показаният psql
примерите не са нещата, които клиентски адаптер като Perl DBI наистина използва. Той използва определен протокол
. Тук терминът "обикновена заявка" съответства на "неподготвена заявка" в psql
, терминът "разширена заявка " отговаря на "подготвена заявка" с едно изключение:Има разлика между (един) "ненаименуван израз" и (евентуално множество) "наименувани изрази". По отношение на наименуваните изрази doc
казва:
и също:
Така че в този случай планирането се извършва без параметри, както е описано по-горе за PREPARE
- нищо ново.
Споменатото изключение е "неназованото изявление". Докторът казва:
И ето ползата:Въпреки че неназованият оператор е „подготвен“ (т.е. може да има заместване на параметри), той също може да адаптира плана на заявката към действителните параметри.
Между другото:Точното обработване на ненаименования оператор се променя няколко пъти в миналите версии на сървъра PostgreSQL. Можете да потърсите подробности в старите документи, ако наистина искате.
Обосновка - Perl / всеки клиент :
Как клиент като Perl използва протокола е съвсем различен въпрос. Някои клиенти като JDBC драйвера за Java основно казват:Дори ако програмистът използва подготвен оператор, първите пет (или нещо такова) изпълнение се нанасят вътрешно на "проста заявка" (т.е. ефективно неподготвен), след което драйверът превключва на " наименувано изявление“.
Така че клиентът има следните възможности за избор:
- Принудително (повторно) планиране всеки път с помощта на протокола „проста заявка“.
- План веднъж, изпълнете няколко пъти, като използвате протокола "разширена заявка" и "наименуваната инструкция" (планът може да е лош, защото планирането се извършва без параметри).
- Синтактичен анализ веднъж, планирайте за всяко изпълнение (с текущата версия на PostgreSQL), като използвате протокола за "разширена заявка" и "неименувания израз" и се подчинявате на още някои неща (предоставете някои параметри по време на съобщението "parse")
- Играйте напълно различни трикове като JDBC драйвера.
Какво прави Perl в момента:не знам. Но споменатата "червена херинга" не е много малко вероятна.