Как я могу проиндексировать этот запрос в Postgresql?

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

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

Я использую три таблицы с 10k, 100k и 100k записями в каждой. См. код ниже. И моя версия 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 секунд.

Посмотрите на тег postgresql-производительность и следуйте рекомендациям, чтобы улучшить свой вопрос.

Mike Sherrill 'Cat Recall' 29.05.2019 22:42

Я бы начал с перезаписи, чтобы использовать синтаксис normalai JOIN ... ON, который облегчит чтение и просмотр того, какие столбцы из каждой дополнительной таблицы соединяются, и выиграет от индекса.

Shawn 29.05.2019 23:16
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
2
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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);

Это мне очень помогло. Спасибо!

Marcus Vincius Natrielli 07.06.2019 23:58

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