2010-08-31 2 views
0

У меня есть таблица с строками 300K и индексом b-дерева в поле «operator». Пока я запускаю этот запрос, он не использует индекс. «Оператор» имеет тот же тип данных, что и dict.vw_dict_operator.id.Почему индекс не используется для этого запроса?

EXPLAIN SELECT 
    id, 
    name 
FROM 
    dict.vw_dict_operator self 
WHERE 

      EXISTS (
       SELECT 42 FROM ti.ti_flight_availability flight_avail 
       WHERE flight_avail.operator = self.id 
      ) 
ORDER BY 
    self.name 

"Sort (cost=3349.66..3351.02 rows=545 width=18)" 
" Sort Key: dict_operator.name" 
" -> Seq Scan on dict_operator (cost=0.00..3324.89 rows=545 width=18)" 
"  Filter: ((NOT trash) AND (subplan))" 
"  SubPlan" 
"   -> Seq Scan on ti_flight_availability flight_avail (cost=0.00..8513.66 rows=3750 width=0)" 
"    Filter: (operator = $0)" 

UPD: thanks @gbn. индекс не используется при объединении таблиц

EXPLAIN SELECT self.id, self.name 
FROM dict.vw_dict_operator self JOIN ti.ti_flight_availability flight_avail 
ON flight_avail.operator = self.id 

"Nested Loop (cost=0.00..92988.47 rows=228639 width=18)" 
" -> Seq Scan on ti_flight_availability flight_avail (cost=0.00..7754.33 rows=303733 width=4)" 
" -> Index Scan using pk_dict_operator on dict_operator (cost=0.00..0.27 rows=1 width=18)" 
"  Index Cond: (dict_operator.id = flight_avail.operator)" 
"  Filter: (NOT dict_operator.trash)" 
+0

Я не знаю об использовании индекса, но зависимые подзапросы обычно являются плохими mojo. – Powerlord

+0

@R. Bemrose Не могли бы вы написать реализацию для этой задачи без подзапросов, пожалуйста? – noxvile

ответ

2

Почему вы не используете JOIN? И вы АНАЛИЗИ? Как насчет статистики? Проверьте pg_stats для этой таблицы, чтобы получить дополнительную информацию. reltuples и relpages в pg_class также интересны для таблицы и ее индексов.


Edit: Соединить ожидает 228639 строк. Последовательное сканирование ожидает 303733 строк, только дополнительная доплата. Когда эти 100k-записи повсюду, база данных должна сканировать переходы в любом случае. Последовательное сканирование будет быстрее, чем сканирование индексов, последовательное сканирование (быстрое) чтение секвенции, сканирование индекса - это два (!) Медленных случайных чтения: информация из индекса и данные из таблицы.

Если вы считаете, что план неверен, ANALYZE таблицу и покажите нам информацию из pg_stats и pg_class о таблицах и индексах.

ANALYZE; 

SELECT relpage, reltuples WHERE relname = 'table_or_index_name'; 

SELECT * FROM pg_stats WHERE tablename = 'name of your table'; 
+0

извините, JOIN не использует индекс тоже. его требуется много времени, чтобы выполнить ANALYZE. reltuples: 303733 relpages: 4717 К сожалению, у меня нет идеи, какую полезную информацию я могу извлечь из pg_class, pg_stats – noxvile

+0

См. Мое редактирование, и вы должны ANALYZE. Вы можете сделать это только на этих таблицах, но вы должны это сделать. Какая версия PostgreSQL у вас есть? –

+0

версия 8.3 reltuples: 303733 relpages: 4717 http://img203.imageshack.us/img203/1516/screenshotrz.png – noxvile

0

Будет ли он использовать индекс, если вы сделали соединение?

0

Какой у вас указатель на dict.vw_dict_operator?

EXISTS - это форма JOIN (упрощенная, я знаю), и, возможно, индекс игнорируется, потому что нет подходящего для JOIN. Поэтому он сканирует вместо этого.

Edit:

Соединить план не используя индекс ti_flight_availability либо ... но вы утверждаете, у вас есть индекс на нем?

+0

CREATE TABLE dict.dict_operator ( ID целое число NOT NULL, CONSTRAINT pk_dict_operator PRIMARY KEY (ID) ) – noxvile

+0

@noxvile: и на ti_flight_availability? – gbn

+0

CREATE INDEX ix_ti_flight_availability_operator ON ti.ti_flight_availability ИСПОЛЬЗОВАНИЕ btree (оператор); – noxvile

Смежные вопросы