2012-03-02 3 views
0

Использование PHP 5.3.10 в отношении (довольно старого) PostgreSQL 8.2.23 базы данных.pg_query_params и его частичный индекс

Я использую запрос, как это:

SELECT * FROM mytable WHERE status = 1 AND id = 123456; 

Я создал частичный индекс для повышения производительности:

CREATE INDEX i1 ON mytable (id) WHERE status = 1; 

Проблема, когда я использую pg_query_params, кажется, что частичный индекс не используется (и запрос выполняется очень медленно):

pg_query_params('SELECT * FROM mytable WHERE status = $1 AND id = $2', array(1,123456)); 

Я тестирую тот же PHP co de в базе данных PostgreSLQ 9.1 и, похоже, хорошо работает (используется индекс). К сожалению, сейчас я не могу перейти на 9.1. Более быстрое обходное решение для меня, кажется, не использует частичный индекс ...

Есть ли известные ограничения с pg_query_params и частичный индекс по старым версиям PG? У меня есть обходное решение, кроме как избежать частичного индекса при использовании pg_query_params?

EDIT:

Вот план выполнения, на 8.2.23 сервере и 9.1.2 сервера. Запрос выполняется (РНР) было:

EXPLAIN ANALYZE SELECT * FROM mytable WHERE status = $1 AND id = $2 

НО, странное поведение, когда на самом деле выполнения запроса (я имею в виду удаление «EXPLAIN ANALYZE») на PG 9.1, используя pg_prepare, запрос, кажется, не использовать индекс (симптом: очень медленный запрос, несколько секунд ... как сканирование seq !?).

PG 8,2, используя pg_query_params:

Seq Scan on mytable (cost=0.00..289976.55 rows=1 width=6) (actual time=851.956..3112.038 rows=1 loops=1) 

PG 8.2, используя pg_prepare + pg_execute:

Seq Scan on mytable (cost=0.00..289976.55 rows=1 width=6) (actual time=399.486..1595.102 rows=1 loops=1) 

PG 9.1, используя pg_query_params:

Index Scan using i1 on mytable (cost=0.00..9.61 rows=1 width=6) (actual time=0.046..0.047 rows=1 loops=1) 

PG 9,1, используя pg_prepare + pg_execute:

Index Scan using i1 on mytable (cost=0.00..9.61 rows=1 width=6) (actual time=0.043..0.043 rows=1 loops=1) 

=> но, как я сказал, реальная продолжительность последнего pg_execute на PG 9.1 1'860 мс !!

+0

Не могли бы вы опубликовать, что объясняет, говорит о вашем запросе? – dezso

+0

Ну, у меня нет объяснений, чтобы проиллюстрировать проблему, потому что, когда я выполняю запрос шаблона (заменяя $ 1 whith value 1 и $ 2 любым целым числом), эффективно используется индекс i1. Я только заметил, что при удалении из индекса ИЛИ условия использования WHERE status = 1, при использовании pg_query вместо pg_query_params запрос выполняется быстро (всего несколько мс, поэтому я полагаю, что этот индекс используется), тогда как с частичным индексом и pg_query_params запрос занимает до 20 секунд ... –

+0

Что произойдет, если вы сначала выполните pg_prepare, а затем запустите pq_execute? – dezso

ответ

1

Проблема с подготовленным заявлением заключается в том, что во время подготовки он не знает, какие значения могут возникнуть позже. В условиях индекса указано состояние WHERE = 1, но будет ли запрос иметь значение «статус = 1»? Трудно предсказать.

Для запроса, как это, используя подготовленное заявление, индекс на обоих условий может быть лучшим вариантом производительности:

CREATE INDEX idx_id_status ON mytable (id, status); 

Это работает в версии 8.2 и 9.1.

+0

Хорошо, но pg_query_params НЕ является подготовленным оператором (=> это pg_prepare/pg_execute). Если я выполняю pg_query_params в 8.2, он не использует индексный план, но на сервере 9.1 он, похоже, использует индексный план. Я тестировал один и тот же запрос с pg_prepare, и кажется, что он никогда не использует индексный план, ни 8.2, ни 9.1 (и это нормально с частичным индексом, как вы объяснили хорошо) –

+0

Я так не думаю. Из руководства: «pg_query_params - отправляет команду на сервер и ждет результата, с возможностью передавать параметры отдельно от текста команды SQL». Проверьте свой журнал запросов, чтобы увидеть инструкцию SQL, которая отправляется (и, таким образом, подготовлена). http://stackoverflow.com/questions/1316830/to-understand-queries-in-php-pg-prepared-statemens –

+0

Но почему же pg_query_params намного быстрее, чем pg_prepare + pg_execute на PostgreSQL 9.1 ?? На мой взгляд, pg_query_params не рассматривается как подготовленный оператор движком ... –