我正在使用Fluent-NHibernate(使用自动化)来生成我的表,但是想要选择与默认使用的ID字段不同的聚簇索引。如何在默认主键字段以外的字段上使用Fluent NHibernate创建聚簇索引?
这背后的主要原因很简单。我正在使用Guids作为我的主键字段。默认情况下,NHibernate在主键字段上创建聚簇索引。由于Guids通常不是顺序的,因此主键字段上的群集会导致性能问题。
众所周知,在表格末尾附加记录比在表格中插入记录要便宜得多。此外,表中的记录按聚集索引中的项目顺序物理存储。由于Guids有点“随机”而且不是连续的,因此可能会生成小Guids,这些Guid小于表中已有的其他Id Guids的值 - 导致表插入而不是追加。
为了最大限度地减少这种情况,我有一个名为CreatedOn的列,其类型为DateTime。我需要将表聚集在此CreatedOn列上,以便附加所有新记录而不是插入。
欢迎任何关于如何实现这一目标的想法!!!
注意:我意识到我可以使用顺序指南,但出于安全原因,我不想走这条路。
注意:我仍然没有这篇文章的答案,但我现在有一些想法。
使用NHibernate而不使用Fluent,我认为可以直接在NHibernate中创建聚簇索引。我还不太了解NHibernate知道如何做到这一点。我很漂亮(几乎绝对是)确定可以做到。
Fluent-NHibernate过去常常包含一种在最近重写之前在SQL对象上设置属性(例如像聚簇索引)的方法。现在这个选项似乎已经消失了。我可能会在某处发布一个问题,看看该选项是否仍然可用。如果是这样,我可能会用它来设置聚集索引。
Fluent-NHibernate能够在流畅构建后公开配置以进行手动编辑。我没有尝试过这个功能,但希望它可以提供设置聚簇索引所需的粒度级别。
最糟糕的情况是,我可以编写一个SQL脚本来在生成所有表后更改聚簇索引。但是,我对这种方法有几个问题。答:由于我使用自动模式生成,NHibernate会在下次评估配置时“撤消”我的聚簇索引吗? 2.如果检测到聚簇索引已更改,NHibernate会出错吗?我需要测试一下,但还没有这样做。我真的很讨厌这个解决方案。我正在测试我的数据库对SQLServer2008和MySQL。 NHibernate的一部分优点是它与数据库无关。一旦我们介绍了脚本,所有的赌注都将被取消。
在名为IPropertyInstance Classes的流畅约定中使用了一个接口,该接口从此接口继承了一个Index属性,该属性允许在该字段上创建索引。问题是没有标志或其他选项允许将索引创建为群集。最简单的解决方案是向此方法添加属性以允许创建聚簇索引。我想我可以向Fluent-NHibernate开发人员提出建议。
答案 0 :(得分:7)
这是一个老帖子,但我希望可以帮助其他人。这来自我在MS SQL Server上的经验。我认为不同的平台需要不同的解决方案,但这应该是一个很好的起点。
NHibernate没有在主键上设置CLUSTERED索引。这是SQL Server的默认行为。由于每个表只能有一个CLUSTERED,我们首先需要避免在主键上创建CLUSTERED。
我发现完成此任务的唯一方法是创建一个自定义Dialect,覆盖有效的PrimaryKeyString。 NHibernate的默认值来自 Dialect.cs :
public virtual string PrimaryKeyString
{
get { return "primary key"; }
}
对于SQL Server
public override string PrimaryKeyString
{
get { return "primary key nonclustered"; }
}
这将强制SQL Server创建NONCLUSTERED主键。 现在,您可以通过XML映射文件中的标记在您喜欢的列上添加自己的CLUSTERED索引。
<database-object>
<create>
create clustered index IX_CustomClusteredIndexName on TableName (ColumnName ASC)
</create>
<drop>
drop index IX_CustomClusteredIndexName ON TableName
</drop>
</database-object>
答案 1 :(得分:1)
我无法回答这个问题,但是我会在这里给你一些数据库信息。
您需要告诉NHibernate在非聚集索引处创建主键。每个表只能有聚簇索引,因此您需要将表创建为堆,然后在其上放置聚簇索引。
答案 2 :(得分:1)
正如你自己所说,另一种选择是切换到guid.comb ID生成策略,其中PK uid基于Guid的一部分,以及确保生成的ID是顺序的部分。
在Jeffrey Palermo here的帖子中查看更多信息。
但是你提到出于安全原因不想这样做 - 为什么会这样?
答案 3 :(得分:0)
就像@ abx78所说的那样,这是一篇很老的帖子,但我想分享一下这个问题的解决方案。我为想法3“Fluent NHibernate公开映射”构建了解决方案:
在构建配置之后(因此解析了映射),Fluent NHibernate为我们提供了查看configuration.ClassMappings
和configuration.CollectionMappings
的实际映射的机会。后者在下面的示例中用于设置复合主键,从而在Sql Server中生成聚簇索引(如@ abx78指出):
foreach (var collectionMapping in configuration.CollectionMappings) {
// Fetch the columns (in this example: build the columns in a hacky way)
const string columnFormat = "{0}_id";
var leftColumn = new Column(string.Format(
columnFormat,
collectionMapping.Owner.MappedClass.Name));
var rightColumn = new Column(string.Format(
columnFormat,
collectionMapping.GenericArguments[0].Name));
// Fetch the actual table of the many-to-many collection
var manyToManyTable = collectionMapping.CollectionTable;
// Shorten the name just like NHibernate does
var shortTableName = (manyToManyTable.Name.Length <= 8)
? manyToManyTable.Name
: manyToManyTable.Name.Substring(0, 8);
// Create the primary key and add the columns
// >> This part could be changed to a UniqueKey or to an Index
var primaryKey = new PrimaryKey {
Name = string.Format("PK_{0}", shortTableName),
};
primaryKey.AddColumn(leftColumn);
primaryKey.AddColumn(rightColumn);
// Set the primary key to the junction table
manyToManyTable.PrimaryKey = primaryKey;
// <<
}
来源:Fluent NHibernate: How to create a clustered index on a Many-to-Many Join Table?