Postgres используя индекс локально, но не в производстве - PullRequest
0 голосов
/ 06 февраля 2020

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

Указанный индекс находится в столбце JSONB.

I перестроил индексы в рабочей среде, чтобы увидеть, не в этом ли проблема, но это не имело значения.

Как можно отладить (или исправить) производство, не используя индексы должным образом?

Вот DDL таблицы и ее индексы.

-- Table Definition ----------------------------------------------

CREATE TABLE tracks (
    id BIGSERIAL PRIMARY KEY,
    album_id bigint REFERENCES albums(id),
    artist_id bigint REFERENCES artists(id),
    duration integer,
    explicit boolean,
    spotify_id text,
    link text,
    name text,
    popularity integer,
    preview_url text,
    created_at timestamp without time zone NOT NULL,
    updated_at timestamp without time zone NOT NULL,
    audio_features jsonb,
    lyrics text,
    lyrics_last_checked_at timestamp without time zone,
    audio_features_last_checked timestamp without time zone
);

-- Indices -------------------------------------------------------

CREATE UNIQUE INDEX tracks_pkey ON tracks(id int8_ops);
CREATE INDEX index_tracks_on_album_id ON tracks(album_id int8_ops);
CREATE INDEX index_tracks_on_artist_id ON tracks(artist_id int8_ops);
CREATE INDEX index_tracks_on_spotify_id ON tracks(spotify_id text_ops);
CREATE INDEX index_tracks_on_explicit ON tracks(explicit bool_ops);
CREATE INDEX index_tracks_on_lyrics_last_checked_at ON tracks(lyrics_last_checked_at timestamp_ops);
CREATE INDEX index_tracks_on_audio_features ON tracks USING GIN (audio_features jsonb_ops);
CREATE INDEX index_tracks_on_audio_features_energy ON tracks(((audio_features ->> 'energy'::text)::numeric) numeric_ops);
CREATE INDEX index_tracks_on_audio_features_tempo ON tracks(((audio_features ->> 'tempo'::text)::numeric) numeric_ops);
CREATE INDEX index_tracks_on_audio_features_key ON tracks(((audio_features ->> 'key'::text)::numeric) numeric_ops);
CREATE INDEX index_tracks_on_audio_features_danceability ON tracks(((audio_features ->> 'danceability'::text)::numeric) numeric_ops);
CREATE INDEX index_tracks_on_audio_features_acousticness ON tracks(((audio_features ->> 'acousticness'::text)::numeric) numeric_ops);
CREATE INDEX index_tracks_on_audio_features_speechiness ON tracks(((audio_features ->> 'speechiness'::text)::numeric) numeric_ops);
CREATE INDEX index_tracks_on_audio_features_instrumentalness ON tracks(((audio_features ->> 'instrumentalness'::text)::numeric) numeric_ops);
CREATE INDEX index_tracks_on_audio_features_valence ON tracks(((audio_features ->> 'valence'::text)::numeric) numeric_ops);
CREATE INDEX index_tracks_on_audio_features_last_checked ON tracks(audio_features_last_checked timestamp_ops);

Вот запрос, который я выполняю.

EXPLAIN ANALYZE SELECT  "tracks".* FROM "tracks" WHERE ((audio_features ->> 'speechiness')::numeric between 0.1 and 1.0)

Вот вывод локально.

Bitmap Heap Scan on tracks  (cost=209.20..2622.49 rows=5943 width=616) (actual time=23.510..179.007 rows=5811 loops=1)
  Recheck Cond: ((((audio_features ->> 'speechiness'::text))::numeric >= 0.1) AND (((audio_features ->> 'speechiness'::text))::numeric <= 1.0))
  Heap Blocks: exact=1844
  ->  Bitmap Index Scan on index_tracks_on_audio_features_speechiness  (cost=0.00..207.72 rows=5943 width=0) (actual time=21.463..21.463 rows=5999 loops=1)
        Index Cond: ((((audio_features ->> 'speechiness'::text))::numeric >= 0.1) AND (((audio_features ->> 'speechiness'::text))::numeric <= 1.0))
Planning Time: 10.248 ms
Execution Time: 179.460 ms

А вот и выход в производство.

Gather  (cost=1000.00..866366.71 rows=607073 width=1318) (actual time=0.486..100252.108 rows=606680 loops=1)
  Workers Planned: 4
  Workers Launched: 3
  ->  Parallel Seq Scan on tracks  (cost=0.00..804659.41 rows=151768 width=1318) (actual time=0.211..99938.152 rows=151670 loops=4)
        Filter: ((((audio_features ->> 'speechiness'::text))::numeric >= 0.1) AND (((audio_features ->> 'speechiness'::text))::numeric <= 1.0))
        Rows Removed by Filter: 731546
Planning Time: 3.029 ms
Execution Time: 100292.766 ms

1 Ответ

0 голосов
/ 06 февраля 2020

Данные сильно различаются в обеих базах данных, поэтому неудивительно, если один и тот же запрос выполняется по-разному.

Рабочий запрос возвращает более 17% строк в таблице, что, очевидно, так почти что PostgreSQL считает, что выполнять последовательное сканирование дешевле.

В целях тестирования вы можете установить enable_seqscan на off в своем сеансе, снова выполнить запрос и проверить, правильно ли было PostgreSQL .

Если вы выбрали не все столбцы из таблицы, а только столбцы, которые проиндексированы, а таблица недавно была очищена, вы можете получить сканирование только для индекса , которое будет намного быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...