Как я могу проиндексировать этот запрос в Postgresql? - PullRequest
0 голосов
/ 29 мая 2019

Я пытаюсь проиндексировать свой запрос, чтобы оптимизировать время выполнения. Я попробовал некоторые b-tree, hash, GIN и GISP index, но ни один из них не использовался планировщиком Postgres. И даже когда я определяю enable_seqscan = OFF, чтобы принудительно использовать мои индексы, время выполнения сохраняется или ухудшается. Как я могу эффективно индексировать этот запрос?

Obs: английский не является моим основным языком, поэтому извините за любые текстовые проблемы

Я использую три таблицы, по 10 000, 100 000 и 100 000 записей в каждой. Смотрите код ниже. И моя версия PostgreSQL - 9.6.

Некоторые индексы, которые я пробовал:

-CREATE INDEX trgm_curso_index ON curso USING gin (nome_curso gin_trgm_ops);
-CREATE INDEX trgm_natureza_index ON instituicao USING gin (natureza_administrativa gin_trgm_ops);
-CREATE INDEX fk_curso ON curso(sigla, campus);
-CREATE INDEX fk_campus ON campus(sigla);
-CREATE INDEX curso_index ON curso (nome_curso);

Мои таблицы:

CREATE TABLE instituicao (
sigla varchar(10),
nome_instituicao varchar(55) NOT NULL,
natureza_administrativa varchar(7) NOT NULL CHECK (natureza_administrativa IN ('Pública', 'Privada')),
nota_IGC smallint NOT NULL CHECK (nota_IGC >= 0 AND nota_IGC <= 5),

PRIMARY KEY(sigla)
);

CREATE TABLE campus(
nome_campus varchar(55) NOT NULL,
estado char(2) NOT NULL CHECK (estado IN ('AC', 'AL', 'AP', 'AM', 'BA', 'CE', 'DF', 'ES', 'GO', 'MA', 'MT', 'MS', 'MG', 'PA', 'PB', 'PR', 'PE', 'PI', 'RJ', 'RN', 'RS', 'RO', 'RR', 'SC', 'SP', 'SE', 'TO')),
cidade varchar(55) NOT NULL,
sigla varchar(10),

PRIMARY KEY(sigla, nome_campus),
FOREIGN KEY(sigla) REFERENCES instituicao(sigla) ON DELETE CASCADE ON UPDATE CASCADE
);

CREATE TABLE curso(
nome_curso varchar(55) NOT NULL,
area varchar(30) NOT NULL CHECK (area IN ('Ciências Exatas e da Terra', 'Ciências Biológicas', 'Engenharias', 'Ciências da Saúde', 'Ciências Agrárias', 'Ciências Sociais Aplicadas', 'Ciências Humanas', 'Linguística, Letras e Artes', 'Outros')),
nota_enade smallint NOT NULL CHECK (nota_enade >= 0 AND nota_enade <= 5),
grau varchar(12) NOT NULL CHECK (grau IN ('Bacharelado', 'Licenciatura', 'Mestrado', 'Doutorado', 'Tecnólogo')),
turno varchar(10) NOT NULL CHECK (turno IN ('Matutino', 'Integral', 'Noturno', 'Vespertino')),
duracao smallint NOT NULL CHECK (duracao > 0 AND duracao <= 12),
ano_criacao smallint NOT NULL CHECK (ano_criacao <= DATE_PART('YEAR', CURRENT_DATE) AND ano_criacao > 1980),
campus varchar(55) NOT NULL,
sigla varchar(10) NOT NULL,

PRIMARY KEY(sigla, campus, nome_curso),
FOREIGN KEY(sigla, campus) REFERENCES campus(sigla, nome_campus) ON DELETE CASCADE ON UPDATE CASCADE
);

Мой запрос:

SELECT curso.sigla, estado, campus, cidade, nome_curso, grau, turno, 
duracao, nota_enade 
FROM instituicao, campus, curso
WHERE instituicao.sigla = campus.sigla AND campus.nome_campus = 
curso.campus AND campus.sigla = curso.sigla AND natureza_administrativa = 
'Pública' AND nome_curso LIKE 'C%'
ORDER BY curso.sigla, estado, cidade;

Фактическое время выполнения в моей записной книжке составляет 3,6-5,7 секунды, но мне нужно достичь максимума в 1-2 секунды.

1 Ответ

0 голосов
/ 30 мая 2019

Вы должны как можно больше подумать о составных индексах, каждый из которых охватывает соединения и фильтр.Попробуйте, если следующие индексы помогают.

CREATE INDEX curso_n_c_s
             ON curso
                (nome_curso,
                 campus,
                 sigla);
CREATE INDEX campus_n_s
             ON campus
                (nome_campus,
                 sigla);
CREATE INDEX instituicao_na_s
             ON instituicao
                (natureza_administrativa,
                 sigla);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...