Почему 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;
Второй запрос в приведенной выше скрипте должен использовать сканирование только по индексу.