No SQL Server, a exibição indexada é um inferno de limitações. Mas eu preciso de um. Eu tenho uma função SQLCLR do formatador que cria uma versão embelezada de uma chave de domínio - os usuários querem poder pesquisar em substrings dessa versão embelezada. Portanto, preciso de um índice de texto completo em uma coluna calculada persistente ou em uma exibição materializada.
No entanto, o formatador depende dos dados armazenados em várias tabelas.
Portanto, isso funciona bem para uma exibição, mas não para uma coluna computada persistente porque elas não podem consultar várias tabelas.
Meu método SQLCLR é preciso e determinístico , portanto, deve ser qualificado para uso em exibições indexadas, mas exibições indexadas não podem ter SQLCLR em suas chaves de índice.
Eu poderia reimplementar meu formatador usando a FORMAT
função T-SQL... mas tambémFORMAT
é incompatível com exibições indexadas.
As visualizações indexadas podem fazer alguma coisa ? Nunca ?
Estou aberto à abordagem "role sua própria visão materializada com gatilhos" se alguém puder me indicar um bom documento sobre as melhores práticas para fazer isso. Da última vez que tentei, ele saiu do controle e houve uma tremenda duplicação entre o código para inserção e atualização e a inicialização.
Existe alguma maneira que estou perdendo para obter pesquisas de texto com desempenho em dados calculados em alguns milhões de linhas, sem usar uma exibição materializada/indexada ou uma coluna calculada persistente?
O formatador não realiza acesso aos dados. No entanto, os dados que preciso alimentar no formatador para que seja útil virão de várias tabelas (com uma boa junção regular), portanto, não posso resolver esse problema com colunas computadas persistentes. Não consigo digitar a coluna SQLCLR, portanto, não posso usá-la em um índice de texto completo.
Achei que isso seria simples. Colunas persistentes e exibições indexadas são projetadas para realizar cálculos na gravação e para implementar adequadamente o padrão de observador para que as alterações em suas dependências sejam refletidas no valor calculado.
Na verdade, é meio miserável quando você pensa em uma exibição indexada como uma solução, apenas para descobrir que seu caso de uso atinge uma das muitas limitações das exibições indexadas (estou olhando para você,
LEFT JOIN
).Você está certo de que não pode incluir o SQLCLR nas chaves de índice da exibição indexada. No entanto, você pode incluí-lo na
SELECT
lista da definição de exibição, que persistirá o valor no disco. Assim, você pode pelo menos evitar o custo de calcular o valor em tempo real ao ler a tabela.No banco de dados de exemplo AdventureWorks2014, criei esta exibição na
Person.Person
tabela com um nome encantador:Nota: eu estava com preguiça de escrever minha própria função CLR, então esta é deste Q&A .
Eu posso tornar isso uma exibição indexada agrupando-a em
BusinessEntityID
:A procura de um conjunto específico de linhas na tabela produz uma verificação de índice ( link do plano de execução ). Observe a falta de um
Compute Scalar
operador, que normalmente seria usado para produzir o valor de hash. Como o hash é mantido em disco na exibição indexada, isso não é necessário:Eu tive que usar uma
NOEXPAND
dica para fazê-lo usar a visualização.Você notará que os avisos no plano se devem ao fato de que toda a tabela foi varrida para encontrar esses valores, já que não há nenhum índice digitado no
FirstNameHash
.Infelizmente, a tentativa de criar um índice não clusterizado nesse valor persistente falha:
Isso ocorre porque o SQL Server não confia em nós :
Imagino que a mesma limitação exista para índices de texto completo, embora eu não tenha tentado.
A conclusão de tudo isso, como você mencionou em seu próprio post, é que você está meio preso aqui. Realmente sua única opção é:
Um índice de texto completo não pode ser criado em uma coluna não determinística.
Esse erro foi produzido ao tentar indexar em texto completo a
Search
coluna definida em uma exibição indexada conforme abaixo:As funções referenciadas lá são da biblioteca SQL# CLR e estão disponíveis na versão gratuita. Eles correspondem à função da
FORMAT
função, o que não é permitido em uma exibição indexada.No entanto, parece improvável que a pesquisa de texto completo seja o que você precisa. Não é adequado para pesquisas com curingas à esquerda ou correspondência geral de strings onde não-palavras estão envolvidas. Como diz a documentação :
Se você precisar de pesquisas rápidas com curinga e/ou sem idioma, e as funções internas do T-SQL não funcionarem bem o suficiente após o teste, uma alternativa é usar n-grams, como descrevo em Trigram Wildcard String Search em Servidor SQL .
Esse artigo contém uma implementação completa, incluindo gatilhos simples para manter uma fonte de dados (por exemplo, uma exibição indexada como acima) sincronizada com os n-grams o tempo todo, se necessário. Se você não precisar de sincronização ao vivo, poderá descobrir que reconstruir os n-grams completamente de vez em quando é bom o suficiente para seus usuários, pois os gatilhos não são necessários (por mais leves que sejam).