Pergunta

Estou usando o Nibernato Fluente (com Automapping) para gerar minhas tabelas, mas gostaria de escolher um índice em cluster diferente do campo de identificação que é usado por padrão. Como você pode criar índices em cluster com Nibernato fluente em um campo que não seja o campo de chave primária padrão?

O principal raciocínio por trás disso é simples. Estou usando o GUIDS para meus campos principais principais. Por padrão, o Nhibernate cria índices em cluster nos campos principais principais. Como os GUIDs geralmente não são seqüenciais, o cluster no campo principal principal causa um problema de desempenho.

Como todos sabemos, anexar registros no final de uma tabela é uma operação muito mais barata do que a inserção de registros dentro da tabela. Além disso, os registros na tabela são fisicamente armazenados na ordem dos itens no índice em cluster. Como os GUIDs são um pouco "aleatórios" e não são seqüenciais, novos GUIDs podem ser gerados que são menores que o valor de outros guias de identificação já na tabela-resultando em inserções de tabela em vez de anexar.

Para minimizar isso, tenho uma coluna chamada CreateNon, que é do tipo DateTime. Preciso que a tabela seja agrupada nesta coluna Createdon para que todos os novos registros sejam anexados, em vez de inseridos.

Qualquer idéia de como realizar isso é bem -vinda !!!

Nota: percebo que poderia usar guids seqüenciais, mas prefiro não seguir esse caminho por motivos de segurança.


Nota: Ainda não tenho uma resposta para este post, mas tenho algumas idéias que estou pensando no momento.

  1. Usando o Nhibernate sem fluente, acho que pode ser possível criar índices clusterados diretamente no Nibernate. Ainda não sei o suficiente sobre o Nibernate para saber como fazer isso. Eu sou apenas bonita (como quase absolutamente) com certeza que pode ser feito.

  2. O fluente-nibernato usado para incluir uma maneira de definir atributos (por exemplo, como um índice em cluster) em um objeto SQL antes da reescrita recente. Agora essa opção parece ter desaparecido. Provavelmente vou postar uma pergunta em algum lugar para ver se essa opção ainda está disponível. Nesse caso, eu provavelmente poderia usar isso para definir o índice em cluster.

  3. O Fluent-Nibernate fornece a capacidade de expor uma configuração para edição manual depois de construir fluentemente. Não tentei essa funcionalidade, mas espero que possa oferecer o nível de granularidade necessário para definir índices clusterados.

  4. Na pior das hipóteses, posso escrever um script SQL para alterar os índices em cluster em todas as minhas tabelas depois de geradas. No entanto, tenho algumas perguntas sobre essa abordagem. R. Como estou usando a geração automática de esquema, o Nibernate "Desfazer" meu índice em cluster alterações na próxima vez que avaliará a configuração? 2. O Nibernate Erro se detectar o índice em cluster foi alterado? Eu preciso testar isso, mas ainda não o fiz ainda. Eu realmente odeio essa solução. Estou testando meu banco de dados contra o SQLSERVER2008 e MYSQL. Parte da beleza do Nibernate é que é agnóstico do banco de dados. Depois que introduzimos scripts, todas as apostas estão desligadas.

  5. Existe uma interface usada em convenções fluentes chamadas classes iPropertyInstance que herdam dessa interface possuem uma propriedade de índice que permite que um índice seja criado no campo. O problema é que não há sinalizador ou outra opção para permitir que o índice seja criado como clusterado. A solução mais simples seria adicionar uma propriedade a esse método para permitir a criação de índices em cluster. Acho que posso sugerir isso aos desenvolvedores fluentes-nibernados.

Foi útil?

Solução

Este é um post antigo, mas espero que possa ajudar outra pessoa. Isso vem da minha experiência no MS SQL Server. Acredito que diferentes plataformas exigem soluções diferentes, mas esse deve ser um bom ponto de partida.

O Nibernate não define o índice em cluster na chave primária. É o comportamento padrão do SQL Server. Como pode haver apenas um cluster por tabela, precisamos primeiro evitar a criação em cluster na chave primária.

A única maneira que encontrei para conseguir isso é criar um dialeto personalizado, substituindo o Propery PrimaryKeystring. O padrão de Nibernate vem de Dialect.cs:

    public virtual string PrimaryKeyString
    {
        get { return "primary key"; }
    }

Para servidor SQL

    public override string PrimaryKeyString
    {
        get { return "primary key nonclustered"; }
    }

Isso forçará o SQL Server a criar uma chave primária não clusterada. Agora você pode adicionar seu próprio índice em cluster na sua coluna favorita através da tag no arquivo de mapeamento XML.

<database-object>
  <create>
    create clustered index IX_CustomClusteredIndexName on TableName (ColumnName ASC)
  </create>
  <drop>
    drop index IX_CustomClusteredIndexName ON TableName
  </drop>
</database-object>

Outras dicas

Não posso responder isso especificamente, mas vou lhe dar algumas informações de banco de dados desde que estou aqui.

Você precisará dizer ao Nibernate para criar a chave primária em um índice não agrupado. Só pode haver apenas índice cluster por tabela, então você precisa criar a tabela como uma pilha e, em seguida, colocar um índice em cluster nela.

Como você disse, outra opção é mudar para a estratégia de geração de identificação do GUID.com, onde os PK UIDs são baseados em uma peça que é um GUID e uma parte que garante que os IDs gerados sejam seqüenciais.

Confira mais informações em um post de Jeffrey Palermo aqui.

Mas você menciona que não quer fazer isso por razões de segurança - por que isso?

Assim como o @Abx78 disse, este é um post antigo, mas eu gostaria de compartilhar meu conhecimento em uma solução para esse problema também. Eu construí a solução para a idéia 3 "Nibernato fluente expõe mapeamentos":

Depois que a configuração foi construída (assim os mapeamentos são analisados), o Nibernato Fluente nos dá a oppertunidade de olhar para os mapeamentos reais com configuration.ClassMappings e configuration.CollectionMappings. Este último é usado no exemplo abaixo para definir uma chave primária composta, resultando em um índice em cluster no SQL Server (como @abx78 aponta):

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;
    // <<
}

Fonte: Nibernato fluente: como criar um índice em cluster em uma tabela de junção com muitos para muitos?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top