Както вече разбрахте, проблемът е свързан с използването на оператори, различни от равни. Индексът може да се използва най-ефективно само за най-левите колони, които се сравняват с равни (плюс едно условие за диапазон).
Във вашия пример:
create index i on t (a,b,c,d);
where a=1 and b=11 and c!=5 and d<8;
Може да използва индекса само за a
и b
ефективно. Това означава, че DB извлича всички редове, съответстващи на a
и b
условие и след това проверява всеки ред спрямо останалите условия.
Когато промените филтъра на c
на равно, извлича (потенциално) по-малко редове (само тези, които съответстват на a
и b
и c
) и след това проверява тези (по-малко) редове спрямо d
филтър. Използването на индекса е по-ефективно в този случай.
Като цяло, програмата за планиране на заявки на PostgreSQL оценява и двете опции:(1) използвайки индекса; (2) извършване на SeqScan. И за двете изчислява разходна стойност — колкото по-висока е тя, толкова по-лоша е очакваната производителност. Следователно, той взема този с по-малка себестойност. Ето как решава дали да използва индекса или не, няма фиксиран праг.
И накрая, по-горе е написано "плюс едно условие за диапазон". Това означава, че може не само да използва индекса по най-ефективния начин, ако използвате знаци за равенство, но и за едно единствено условие за диапазон.
Като се има предвид, че имате едно единствено условие за диапазон в заявката си, предлагам да промените индекса по следния начин:
create index i on t (a,b,d,c);
Сега може да използва филтрите на a
и b
и d
ефективно с индекса и трябва само да филтрира редовете, където c!=5
. Въпреки че този индекс може да се използва по-ефективно за вашата заявка като оригиналния, това не означава автоматично, че PG ще го използва. Зависи от разчетите за разходите. Но опитайте.
И накрая, ако това не е достатъчно бързо и стойността 5
използвате в израза c!=5
е константа, можете да помислите за частичен индекс:
create index i on t (a,b,d)
where c!=5;
Можете да направите това и с всички други колони, ако стойностите, с които ги сравнявате, са константи.
Препратки: