Por que minha consulta não é determinística?
Eu tenho uma consulta que faz o seguinte:
select sum(float1*float2*coalesce(float3,1)) from table
Quando executo essa consulta, obtenho um resultado determinístico, mas parece não ser o caso quando a consulta é executada várias vezes.
O último inteiro no resultado difere entre execuções diferentes.
Todas as colunas são (float,null)
Um truncamento flutuante deve ser o mesmo para todas as execuções?
A multiplicação de valores aproximados multiplicará os erros: às vezes eles se cancelam, mas geralmente exageram
float também é preciso para 15 algarismos significativos no máximo : conforme você multiplica e SOMA, você pode atingir isso rapidamente e perder a precisão.
Acho que as alterações nos resultados dependerão de como a ordem em que os dados são acessados (alterações com, por exemplo, novas linhas, estouro de linha, divisões de página, etc.), portanto, a série de cálculos envolvidos mudará a ordem, cada um com seu próprio arredondamento.
Edit: pensei.
Cada núcleo/soquete fará cálculos flutuantes de forma diferente.
Tente isso para ver se podemos tornar isso determinístico (observe que isso não é o mesmo que "correto")
Adicione MAXDOP 1 à consulta e veja quantos resultados diferentes você obtém. Não estou esperando mais do que o número de núcleos ou soquetes. Isso reduz o número de permutações com paralelismo
Em seguida, tente a afinidade do processador para sempre usar o mesmo núcleo para todas as consultas para forçar a execução da consulta em um núcleo/cpu
Para corrigi-lo, use decimal ou bigint.
Floats, como outros mencionaram, são praticamente não determinísticos. Não há realmente nada que você possa fazer sobre isso, infelizmente.
Por exemplo, se você jogar o número 5 em uma tabela e então truncá-lo, você pode acabar com 4.000, já que 5 pode acabar sendo representado na memória como 4.9999.
Se você tentar contornar isso arredondando, esse é o mesmo problema, pois 5,5 pode realmente ser armazenado como 5,49999, que seria arredondado para 5.
Você pode tentar pequenos truques como adicionar 0,25 e depois truncar, mas acho que isso está perdendo completamente o objetivo do FLOATS.
Em última análise, eles são - por conta própria - bastante não determinísticos. Isso é, curiosamente, um problema com a arquitetura e se espalhará por todo o uso de flutuações no sistema operacional (ou seja, todas as linguagens e aplicativos, incluindo bancos de dados).
Meu primeiro pensamento seria porque float é um numérico aproximado, tornando-o uma função não determinística.
Float não é um tipo de dado exato.