Почему PostgreSQL не использует мои индексы для небольшой таблицы?

У меня есть следующая таблица в PostgreSQL:

CREATE TABLE index_test
(
    id int PRIMARY KEY NOT NULL,
    text varchar(2048) NOT NULL,
    last_modified timestamp NOT NULL,
    value int,
    item_type varchar(2046)
);
CREATE INDEX idx_index_type ON index_test ( item_type );
CREATE INDEX idx_index_value ON index_test ( value )

Я делаю следующее:

explain select * from index_test r where r.item_type='B';
explain select r.value from index_test r where r.value=56;

Объяснение плана выполнения выглядит так:

Последующее сканирование на index_test r  (стоимость =0,00..1.04 строк =1 ширина =1576)
    Фильтр: ((item_type)::text = 'B'::text)'

Насколько я понимаю, это полное сканирование таблицы. Вопрос в том, почему мои индексы не используются?

Может быть, причина в том, что в моей таблице слишком мало строк? У меня есть только 20 из них. Не могли бы вы предоставить мне оператор SQL, чтобы легко заполнить мою таблицу случайными данными для проверки проблемы с индексами?

Я нашел эту статью: http://it.toolbox.com/blogs/db2luw/how-to-easily-populate-a-table-with-random-data-7888, но она не работает для меня. Эффективность утверждения не имеет значения, только простота.

2 ответа

Решение

Может быть, причина в том, что в моей таблице слишком мало строк?

Да. В общей сложности 20 строк в таблице последовательное сканирование всегда будет выполняться быстрее, чем сканирование по индексу. Скорее всего, эти строки в любом случае расположены в одном блоке базы данных, поэтому для сканирования seq потребуется только одна операция ввода-вывода.

Если вы используете

explain (analyze true, verbose true, buffers true) select ....

Вы можете увидеть немного больше информации о том, что на самом деле происходит.

Кстати: вы не должны использовать text в качестве имени столбца, поскольку это также тип данных в Postgres (и, следовательно, зарезервированное слово).

Вы нашли пример для DB2, в pg вы можете использовать generate_series сделать это. Например, вот так:

INSERT INTO index_test(data,last_modified,value,item_type) 
SELECT
    md5(random()::text),now(),floor(random()*100),md5(random()::text) 
    FROM generate_series(1,1000);
SELECT max(value) from index_test;

http://sqlfiddle.com/

Второй запрос в приведенной выше скрипте должен использовать сканирование только по индексу.

Другие вопросы по тегам