У меня та же проблема с таблицами> 300 миллионов записей и индексированным полем с несколькими различными значениями.Я не смог избавиться от сканирования seq, поэтому я сделал эту функцию для имитации отдельного поиска с использованием индекса, если он существует.Если ваша таблица имеет несколько различных значений, пропорциональных общему количеству записей, эта функция не годится.Он также должен быть скорректирован для разных значений столбцов. Предупреждение : эта функция широко открыта для инъекций sql и должна использоваться только в защищенной среде.
Объяснить результаты анализа:Запрос с обычным SELECT DISTINCT: общее время выполнения: 598310,705 мсЗапрос с SELECT small_distinct (...): общее время выполнения: 1,156 мс
CREATE OR REPLACE FUNCTION small_distinct(
tableName varchar, fieldName varchar, sample anyelement = ''::varchar)
-- Search a few distinct values in a possibly huge table
-- Parameters: tableName or query expression, fieldName,
-- sample: any value to specify result type (defaut is varchar)
-- Author: T.Husson, 2012-09-17, distribute/use freely
RETURNS TABLE ( result anyelement ) AS
$BODY$
BEGIN
EXECUTE 'SELECT '||fieldName||' FROM '||tableName||' ORDER BY '||fieldName
||' LIMIT 1' INTO result;
WHILE result IS NOT NULL LOOP
RETURN NEXT;
EXECUTE 'SELECT '||fieldName||' FROM '||tableName
||' WHERE '||fieldName||' > $1 ORDER BY ' || fieldName || ' LIMIT 1'
INTO result USING result;
END LOOP;
END;
$BODY$ LANGUAGE plpgsql VOLATILE;
Примеры вызовов:
SELECT small_distinct('observations','id_source',1);
SELECT small_distinct('(select * from obs where id_obs > 12345) as temp',
'date_valid','2000-01-01'::timestamp);
SELECT small_distinct('addresses','state');