2011-01-06 3 views
1

У меня есть таблица с 5 миллионами + записей в базе данных Informix.Использование индексов (индексов?) В Informix DB

Это не фактический стол, но покажет проблему, с которой я столкнулся.

Таблица: продажа
Колонки: sale_id, sale_confirmed, VENDOR_ID, purchaser_id
Индексы: idx1 (sale_id), idx2 (sale_confirmed), idx3 (VENDOR_ID), idx4 (purchaser_id)

Если я сделать запрос например:

select * 
from sales 
where sale_confirmed IS NULL 
or sale_confirmed = '' 

затем запрос завершается примерно через 4 или 5 секунд.

Если я сделать запрос, как это:

select * 
from sales 
where vendor_id = 12345 
or purchaser_id = 12345 

то запрос выполняется до завершения в течение примерно 4 или 5 секунд.

Однако, если я запускаю этот запрос (комбинации из 2-х предыдущих запросов):

select * 
from sales 
where (sale_confirmed IS NULL 
     or sale_confirmed = '') 
and (vendor_id = 12345 
     or purchaser_id = 12345) 

то запрос побежал в течение 15 минут, прежде чем я отменил его.

База данных не кажется достаточно умной, чтобы использовать разные индексы в тандеме, то есть, похоже, она не может использовать idx2 для поиска X числа строк И использовать idx3 и idx4 в пределах этого количества X строк - Правильно, я бы подумал, что это будет достаточно умен, чтобы это сделать?

Есть ли способ заставить базу данных использовать idx3 и idx4 при обработке второй части предложения WHERE?

Любые другие решения, не создающие новые индексы?

Спасибо.

+0

Какую версию IDS вы используете? Ваша статистика достаточно актуальна? Вы посмотрели планы запросов с помощью SET EXPLAIN ON? –

ответ

2

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

select * 
from sales 
where (sale_confirmed IS NULL 
     or sale_confirmed = '') 
and vendor_id = 12345 


UNION 

select * 
from sales 
where (sale_confirmed IS NULL 
     or sale_confirmed = '') 
and purchaser_id = 12345 

И если Informix поддерживает встроенные взгляды, получить набор строк, основанных на поставщика/покупателя, а затем от set исключить неподтвержденные продажи.

select inlineview.* from 
(
select * from sales 
where vendor_id = 12345 or purchaser_id = 12345 
) as inlineview 
where (sale_confirmed IS NULL or sale_confirmed = '') 

Наконец, я думаю, вы можете отказаться от индекса низкой мощности на sales_confirmed.

P.S. Обычно у меня не было столбца в моей базе данных, который допускал бы пустую строку, NULL и другие значения. Я бы привязал поле, вероятно, к типу BIT, если он у вас есть, с 1 и 0, с 0 значением по умолчанию.

+0

+1 для использования UNION. –

1

Индекс «sale_confirmed» вряд ли будет полезен, потому что мощность «sale_confirmed» кажется низкой (NULL, да, нет?). Оптимальный дизайн схемы будет принудительно выполнять NOT NULL на «sale_confirmed», а ограничение CHECK будет обеспечивать «Y» или «N», а значение по умолчанию может дать вам «N», если вы не указали иначе. Это позволит избежать необходимости выполнять операции OR на «sale_confirmed», которые являются беспорядочными.

Метод UNION, предложенный Tim, скорее всего, станет подходящим решением.