2015-12-05 5 views
2

При поиске в Google для соедините таблицы с индексами, я получил this question.Индексы на таблицах объединений

Теперь я считаю, что он дает ложную информацию в принятом ответе, или я не понимаю, как все работает. Учитывая следующие таблицы (бег на PostGreSQL 9.4):

CREATE TABLE "albums" ("album_id" serial PRIMARY KEY, "album_name" text) 
CREATE TABLE "artists" ("artist_id" serial PRIMARY KEY, "artist_name" text) 
CREATE TABLE "albums_artists" ("album_id" integer REFERENCES "albums", "artist_id" integer REFERENCES "artists") 

Я пытался повторить сценарий из вопроса, упомянутого выше, путем создания первого индекса на обоих столбцов albums_artists таблицы, а затем один индекс для каждого столбца (без сохранения индекса на обоих столбцах).

я бы ожидал очень разные результаты при использовании команды EXPLAIN для нормальной, традиционной выбрать, как следующему:

SELECT "artists".* FROM "test"."artists" 
    INNER JOIN "test"."albums_artists" ON ("albums_artists"."artist_id" = "artists"."artist_id") 
    WHERE ("albums_artists"."album_id" = 1) 

Однако, когда на самом деле работает объяснить на нем, я получаю точно такой же результат для каждого из случаев (с одним индексом по каждому столбцу по сравнению с одним индексом на обоих столбцах).

Я читал документацию по PostGreSQL об индексации, и это не имеет никакого смысла на результаты, которые я получаю:

Hash Join (cost=15.05..42.07 rows=11 width=36) (actual time=0.024..0.025 rows=1 loops=1) 
    Hash Cond: (artists.artist_id = albums_artists.artist_id) 
    -> Seq Scan on artists (cost=0.00..22.30 rows=1230 width=36) (actual time=0.006..0.006 rows=1 loops=1) 
    -> Hash (cost=14.91..14.91 rows=11 width=4) (actual time=0.009..0.009 rows=1 loops=1) 
     Buckets: 1024 Batches: 1 Memory Usage: 1kB 
     -> Bitmap Heap Scan on albums_artists (cost=4.24..14.91 rows=11 width=4) (actual time=0.008..0.009 rows=1 loops=1) 
       Recheck Cond: (album_id = 1) 
       Heap Blocks: exact=1 
       -> Bitmap Index Scan on albums_artists_album_id_index (cost=0.00..4.24 rows=11 width=0) (actual time=0.005..0.005 rows=1 loops=1) 
        Index Cond: (album_id = 1) 

Я бы ожидать, чтобы не получить сканирования индекса на последний шаг при использовании индекса, составленного из двух разных столбцов (поскольку я использую только один из них в предложении WHERE).

Я собирался открыть ошибку в библиотеке ORM, которая добавляет один индекс для обоих столбцов для таблиц объединения, но теперь я не уверен. Может ли кто-нибудь помочь мне понять, почему поведение аналогично в двух случаях и что на самом деле будет иметь значение, если они есть?

+0

Этот вопрос по своей сути специфичен для СУБД. Вам нужно пометить его соответствующей СУБД. –

+0

Спасибо за совет. Я добавил тег. –

ответ

4
  • добавить NOT NULL ограничения на ключевых столбцах (кортеж нулей не имеет смысла здесь)
  • добавить PRIMARY KEY (принуждая уникальный индекс на два KeyFields)
  • Как Suport для FK поиски: добавить составной индекс для PK полого в обратном порядке
  • после создания/добавления индексов и первичных ключей, вы можете проанализировать таблицу (только ключевые столбцов есть статистика)

CREATE TABLE albums_artists 
    (album_id integer NOT NULL REFERENCES albums 
    , artist_id integer NOT NULL REFERENCES artists 
    , PRIMARY KEY (album_id, artist_id) 
    ); 

CREATE UNIQUE INDEX ON albums_artists (artist_id, album_id); 

Причиной наблюдаемого поведения является тот факт, что планировщик/Оптимизатор является информация на основе, движимый эвристики. Без какой-либо информации о доле строк, которые действительно понадобятся с учетом условий или доли строк, которые фактически накладываются (в случае JOIN), планировщик делает предположение: (например: 10% для диапазона запрос). Для небольшого запроса хеш-соединение всегда будет выигрышным сценарием, оно подразумевает выборку всех кортежей из обеих таблиц, но само соединение очень эффективно.

Для столбцов, которые являются частью ключа или индекса, статистика будет собираться, поэтому планировщик может сделать более реалистичные оценки количества вовлеченных строк. Ald, который часто приводит к индексированному плану, поскольку для этого может потребоваться меньшее количество страниц для загрузки.

Внешние ключи - это особый случай; поскольку планировщик знает, что все значения из ссылочной таблицы будут указаны в указанной таблице. (то есть 100%, при условии NOT NULL)

+0

Как это ответить на мой вопрос? –

+0

Проблема, лежащая в основе вашего вопроса, заключается в отсутствии базовой структуры таблицы. – wildplasser

+0

Я сделал именно это, и я получаю точно такой же ответ на EXPLAIN. Кроме того, мой вопрос заключается в том, почему происходит это поведение и какова его логика. –