Получение Hibernate для генерации индексов по внешним ключам - PullRequest
9 голосов
/ 04 июня 2010

Я использую Hibernate 3.3.2 в довольно большом проекте с PostgreSQL 8.4 с использованием PostgreSQLDialect.

Как мы настроили наши отношения, мы в итоге выполняем большой поиск по атрибутам внешнего ключанаших столов.

По соображениям производительности я бы хотел, чтобы Hibernate добавил индексы во все столбцы внешнего ключа при создании наших таблиц с использованием hbm2dll.auto.

MySQL автоматически добавит индексы в этистолбцы, но, похоже, в Postgres нет способа сделать это.

Есть ли вариант, который я могу установить где-нибудь, или что-то, что я могу добавить в мои файлы hbm.xml, чтобы это произошло?

Ответы [ 4 ]

2 голосов
/ 04 июня 2010

Вот быстрый и грязный запрос, который сгенерирует DDL для индексов для каждого определенного внешнего ключа в схеме:

SELECT 'CREATE INDEX fk_' || conname || '_idx ON ' 
       || relname || ' ' || 
       regexp_replace(
           regexp_replace(pg_get_constraintdef(pg_constraint.oid, true), 
           ' REFERENCES.*$','',''), 'FOREIGN KEY ','','') || ';'
FROM pg_constraint 
JOIN pg_class 
    ON (conrelid = pg_class.oid)
JOIN pg_namespace
    ON (relnamespace = pg_namespace.oid)
WHERE contype = 'f'
  AND nspname = 'public';

Это было протестировано только в PostgreSQL 8.4, но я думаю, что оно должно работать в большинстве версий 8.x.

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

2 голосов
/ 04 июня 2010

Hibernate обеспечивает создание индекса только для MySQL, а не для PostgreSQL, Oracle и т. Д. MySQL не допускает использование внешних ключей без индекса, другие базы данных не имеют этого ограничения.

Sybase имеет Объяснение почему хорошо не применять индексы, на форуме Hibernate также есть тема (связанная с Oracle), включая обходной путь.Но прежде чем вы начнете создавать множество индексов, начните проверять, нужны ли вам все эти индексы.Во многих случаях индексы могут быть объединены с другими, чтобы ускорить процесс.Все это зависит!

Используйте EXPLAIN в своих запросах, чтобы увидеть, как база данных выполняет их, какие индексы используются, где отсутствуют индексы и т. Д.

1 голос
/ 04 июня 2010

Попробуйте любое из:

<many-to-one name="master" class="Master" column="master_id" index="my_index_name" />

<many-to-one name="master" class="Master">
    <column name="master_id" index="my_index_name" />
</many-to-one>
0 голосов
/ 21 июня 2012

В дополнение к ответу Мэтью: Добавление

AND NOT EXISTS (
  SELECT * FROM pg_class pgc
    JOIN pg_namespace pgn ON (pgc.relnamespace = pgn.oid)
  WHERE relkind='i'
    AND pgc.relname = ('fk_' || conname || '_idx') )

прямо перед точкой с запятой создает индексы, только если они не существуют. Это позволяет вам многократно выполнять оператор, не создавая ошибок «отношения fk _... уже существует»

...