Использование индексов (индексов?) На БД Informix - PullRequest
1 голос
/ 06 января 2011

У меня есть таблица с 5 миллионами + записей в базе данных Informix.

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

Таблица: продажи
Столбцы: 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рядов - это правильно, я бы подумал, что это будет достаточно умен, чтобыo это?

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

Есть ли другие решения, кроме создания новых индексов?

Спасибо.

Ответы [ 2 ]

2 голосов
/ 06 января 2011

Попробуйте использовать 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 поддерживает встроенные представления, получите набор строк на основе поставщика / покупателя, а затем изэтот набор исключает неподтвержденные продажи.

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

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

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

1 голос
/ 06 января 2011

Индекс 'sale_confirmed' вряд ли будет полезен, поскольку количество элементов 'sale_confirmed' кажется низким (NULL, да, нет?).В улучшенном проекте схемы будет реализовано NOT NULL для 'sale_confirmed', а ограничение CHECK приведет к 'Y' или 'N', а значение по умолчанию может дать вам 'N', если не указано иное.Это позволило бы избежать необходимости выполнять операции ИЛИ с 'sale_confirmed', которые являются грязными.

Техника UNION, предложенная Тимом , вероятно, будет достойным обходным путем.

...