O SQL Server armazena em cache o resultado de uma coluna computada não persistente para que possa ser reutilizada sem incorrer em custos de recálculo?
Contexto Adicional Sempre dei o conselho de que, se estiver usando colunas computadas, você deve usar a opção PERSISTED, a menos que esteja esperando uma frequência de inserção/atualização maior do que a frequência de leitura, ou se precisar de melhor desempenho em inserções/atualizações do que as leituras de os dados (ou seja, uma vez que o custo do cálculo deve ser incorrido em um ou outro, então a decisão é realmente onde você quer pagar esse custo).
Há também a consideração do armazenamento adicional para os dados computados, mas normalmente isso é bastante insignificante e barato, portanto, não é muito importante.
No entanto, eu queria verificar se meu conselho é totalmente preciso, já que o SQL pode ser mais inteligente ... consultas. O SQL pode ter um carimbo de data/hora no valor armazenado em cache e outro nos dados do registro subjacente para dizer se esse registro foi alterado desde que o valor calculado foi calculado para determinar se o valor armazenado em cache ainda é válido.
Existe algo assim em vigor / depende dos recursos disponíveis (por exemplo, memória) ou outros fatores (por exemplo, o valor em cache tem um TTL além do tempo de vida do processo)? Eu nunca li nada sugerindo que isso existe, mas ficaria surpreso se não houvesse alguma otimização acontecendo nos bastidores.
Os valores de coluna computados não persistentes não são armazenados em cache na memória.
Aqui está uma breve demonstração que confirma isso. Primeiro vou criar um banco de dados para nossos testes:
E, em seguida, crie uma tabela sem uma coluna computada como linha de base. Os tamanhos de coluna nesta tabela são escolhidos especificamente para que 4 linhas preencham exatamente uma página de dados de 8 KB (e, portanto, uma página de 1 no cache de buffer do SQL Server):
Em seguida, criarei a mesma tabela, mas com a adição de uma coluna computada:
Em seguida, garantirei que essas 8 linhas sejam gravadas no disco e, em seguida, limpe o cache do buffer e selecione todas as 8 linhas para que sejam puxadas para a memória:
Por fim, usarei essa consulta que totalmente não roubei de Aaron Bertrand*
A partir disso, você pode ver que há apenas uma página na memória para cada uma dessas duas tabelas. Se a coluna computada fosse armazenada na memória, ela teria empurrado as linhas da segunda tabela para uma segunda página.
Você também pode ver o cálculo ocorrendo a cada vez no plano de execução real :
Se você precisar "armazenar em cache" colunas computadas não persistentes para consultas específicas, poderá criar um índice não clusterizado nelas. Dessa forma, eles são armazenados no índice, mas não na tabela base.
*consulte Determinar o uso de memória do SQL Server por banco de dados e objeto e aqui está o código: