Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Comprimento DECIMAL para microtime (true)?


tl; dr. Use microtime(false) e armazene os resultados em um MySQL bigint como milionésimos de segundos. Caso contrário, você tem que aprender tudo sobre aritmética de ponto flutuante, que é uma bola de pelo grande e gorda.

A função microtime do PHP pega o timestamp Unix (atualmente cerca de hexadecimal 50eb7c00 ou decimal 1.357.609.984) de uma chamada de sistema e o microssegundo de outra chamada de sistema. Em seguida, ele os transforma em uma cadeia de caracteres. Então, se você chamá-lo com (true), ele converte esse número em um número de ponto flutuante IEEE 745 de 64 bits, uma coisa que o PHP chama de float .

A partir de hoje, você precisa de dez dígitos decimais à esquerda do ponto decimal para armazenar um registro de data e hora UNIX inteiro. Isso permanecerá verdadeiro até cerca de 2280 EC, quando seus descendentes começarão a precisar de onze dígitos. Você precisará de seis dígitos à direita da casa decimal para armazenar os microssegundos.

Você não obterá precisão total de microssegundos. A maioria dos sistemas mantém o relógio do sistema de subsegundos com uma resolução na faixa de 1 a 33 milissegundos. É dependente do sistema.

O MySQL versão 5.6.4 e posterior permite que você especifique DATETIME(6) colunas, que manterão datas e horas com resolução de microssegundos. Se você estiver usando uma versão do MySQL, esse é absolutamente o caminho a seguir.

Antes da versão 5.6.4, você precisa usar MySQL DOUBLE (ponto flutuante IEEE 754 de 64 bits) para armazenar esses números. MySQL FLOAT (IEEE 754 ponto flutuante de 32 bits) não tem bits suficientes em sua mantissa para armazenar até mesmo a hora atual do UNIX em segundos com total precisão.

Por que você está armazenando esses carimbos de data/hora? Você está esperando para fazer
  WHERE table.timestamp = 1357609984.100000

ou consultas semelhantes para procurar itens específicos? Isso é perigoso se você usar números float ou double em qualquer lugar em sua cadeia de processamento (ou seja, mesmo se você usar microtime(true) pelo menos uma vez). Eles são notórios por não serem iguais, mesmo quando você achava que deveriam. Em vez disso, você precisa usar algo assim. O 0.001 ìs chamado "epsilon" no comércio de processamento numérico.
  WHERE table.timestamp BETWEEN 1357609984.100000 - 0.001
                            AND 1357609984.100000 + 0.001

ou algo semelhante. Você não terá esse problema se armazenar esses carimbos de data e hora como decimais ou em milionésimos de segundos em um bigint coluna.

O ponto flutuante IEEE de 64 bits tem 53 bits de mantissa -- de precisão. O timestamp atual UNIX Epoch (segundos desde 1-Jan-1970 00:00Z) vezes um milhão usa 51 bits. Portanto, não há muita precisão extra no DOUBLE se nos preocuparmos com o bit de ordem inferior. Por outro lado, a precisão não se esgotará por alguns séculos.

Você está longe de ficar sem precisão com int64(BIGINT). Se eu estivesse realmente armazenando timestamps de microssegundos apenas para ordenar eles no MySQL, eu usaria DATETIME(6) porque eu teria muita aritmética de datas de graça. Se eu estivesse fazendo um aplicativo de alto volume na memória, usaria int64.