pg_query_params и частичный индекс - PullRequest
0 голосов
/ 02 марта 2012

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

Я использую запрос, подобный этому:

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 в базе данных PostgreSLQ 9.1, и он, кажется, работает хорошо (используется индекс). К сожалению, я не могу перейти на 9.1 на данный момент. Мне кажется, что более быстрый обходной путь не использует частичный индекс ...

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

РЕДАКТИРОВАТЬ:

Вот план выполнения на сервере 8.2.23 и сервере 9.1.2. Выполнен запрос (по PHP):

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

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

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 мс !!

1 Ответ

1 голос
/ 02 марта 2012

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

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

CREATE INDEX idx_id_status ON mytable (id, status);

Это работает в версиях 8.2 и 9.1 какхорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...