让Hibernate在外键上生成索引

9
我在一个比较大的项目中使用 Hibernate 3.3.2 和 PostgreSQL 8.4,使用 PostgreSQLDialect。由于我们设置了许多关系,我们最终会对表的外键属性进行大量搜索。
出于性能方面的考虑,我希望在使用 hbm2dll.auto 创建表时,Hibernate 可以把所有外键列添加索引。
MySQL 会自动为这些列添加索引,但是 Postgres 没有这种方式。
请问是否有任何选项或者要在我的 hbm.xml 文件中添加什么内容才可以实现这个功能?
4个回答

3

以下是一个简单的查询,可以生成架构中每个定义的外键索引的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版本。

还请注意,这不会检测哪些已经被索引覆盖,因此可能会有一些重复。


一旦数据库设置好了,这很有帮助,但对于这个问题,我更感兴趣的是让Hibernate在创建表时为我完成它。虽然这是我其他相关问题的一个很好的答案:https://dev59.com/GnA85IYBdhLWcg3wCfBZ - biggusjimmus
我认为,它不能在带引号的命名变量上工作。 - ravshansbox
@Ravshan:暂且不考虑在数据库表定义中不应使用带引号的名称,这个语句在9.3版本中对我有效:从pg_constraint中选择distinct regexp_replace(regexp_replace(pg_get_constraintdef(oid), '^.REFERENCES', 'CREATE INDEX ON'), ').$', ');') where contype = 'f'。 - Matthew Wood
有时候不可避免地需要使用带引号的标识符(至少出于遗留目的)。 - ravshansbox

2
Hibernate仅对MySQL强制执行索引创建,不适用于PostgreSQL、Oracle等。MySQL不允许没有索引的外键,而其他数据库则没有此限制。
Sybase有一个解释,说明不强制执行索引是一件好事,Hibernate论坛上也有一个关于它的主题(与Oracle有关),包括一个解决方法。但在开始创建大量索引之前,请检查您是否需要所有这些索引。在许多情况下,可以将索引与其他索引组合以加快速度。这完全取决于情况!
使用EXPLAIN查询来查看数据库如何执行查询,使用了哪些索引,缺少哪些索引等等。

4
不强制要求外键有索引是有道理的,但允许这样做似乎是一个好选择。 - biggusjimmus

1
除了Matthew的回答之外: 添加

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_...已经存在”错误。


1

尝试以下任意一种方法:

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

我尝试了这两种方法,但在数据库中搜索应该已创建的索引时却没有结果 =\不确定我可能做错了什么,但我会继续努力。 - biggusjimmus
你是用什么设置的?也许它们没有被“update”添加,但可以通过“create”或“create-drop”添加?另一个想法,它可能是像这个bug一样的问题:http://opensource.atlassian.com/projects/hibernate/browse/HHH-1012 - Konrad Garus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接