AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 150158
Accepted
Julian
Julian
Asked: 2016-09-21 06:25:00 +0800 CST2016-09-21 06:25:00 +0800 CST 2016-09-21 06:25:00 +0800 CST

Maneira preferida de armazenar DateTime

  • 772

Podemos armazenar informações de data e hora de duas maneiras. Qual é a melhor abordagem para armazenar informações de DateTime?

Armazenando data e hora em 2 colunas separadas ou uma coluna usando DateTime ?

Você pode explicar por que essa abordagem é melhor?

(Link para documentos do MySQL para referência, a pergunta é geral, não específica para o MySQL)
Tipos de data e hora: Data e hora

database-design datetime
  • 6 6 respostas
  • 41157 Views

6 respostas

  • Voted
  1. Best Answer
    Hannah Vernon
    2016-09-21T06:36:44+08:002016-09-21T06:36:44+08:00

    Armazenar os dados em uma única coluna é a maneira preferida, pois eles estão inextricavelmente ligados. Um ponto no tempo é uma única informação, não duas.

    Uma maneira comum de armazenar dados de data/hora, empregada "nos bastidores" por muitos produtos, é convertê-los em um valor decimal em que "data" é a parte inteira do valor decimal e "hora" é a fração valor. Assim, 1900-01-01 00:00:00 é armazenado como 0.0 e 20 de setembro de 2016 9:34:00 é armazenado como 42631.39861. 42631 é o número de dias desde 1900-01-01. .39861 é a parte do tempo decorrido desde a meia-noite. Não use um tipo decimal diretamente para fazer isso, use um tipo de data/hora explícito; meu ponto aqui é apenas uma ilustração.

    Armazenar os dados em duas colunas separadas significa que você precisará combinar os valores de ambas as colunas sempre que quiser ver se um determinado momento é anterior ou posterior ao valor armazenado.

    Se você armazenar os valores separadamente, invariavelmente encontrará "bugs" difíceis de detectar. Tomemos por exemplo o seguinte:

    IF OBJECT_ID('tempdb..#DT') IS NOT NULL
    DROP TABLE #DT;
    CREATE TABLE #DT
    (
        dt_value DATETIME NOT NULL
        , d_value DATE NOT NULL
        , t_value TIME(0) NOT NULL
    );
    
    
    DECLARE @d DATETIME = '2016-09-20 09:34:00';
    
    INSERT INTO #DT (dt_value, d_value, t_value)
    SELECT @d, CONVERT(DATE, @d), CONVERT(TIME(0), @d);
    
    SET @d = '2016-09-20 11:34:00';
    
    INSERT INTO #DT (dt_value, d_value, t_value)
    SELECT @d, CONVERT(DATE, @d), CONVERT(TIME(0), @d);
    
    /* show all rows with a date after 2016-07-01 11:00 am */
    SELECT *
    FROM #DT dt
    WHERE dt.dt_value >= '2016-07-01 11:00:00';
    
    /* show all rows with a date after 2016-07-01 11:00 am */
    SELECT *
    FROM #DT dt
    WHERE dt.d_value >= CONVERT(DATE, '2016-07-01')
        AND dt.t_value >= CONVERT(TIME(0), '11:00:00');
    

    No código acima, estamos criando uma tabela de teste, preenchendo-a com dois valores e realizando uma consulta simples nesses dados. O primeiro SELECTretorna as duas linhas, porém o segundo SELECTretorna apenas uma única linha, o que pode não ser o resultado desejado:

    insira a descrição da imagem aqui

    A maneira correta de filtrar um intervalo de data/hora em que os valores estão em colunas discretas, conforme apontado por @ypercube nos comentários, é:

    WHERE dt.d_value > CONVERT(DATE, '2016-07-01') /* note there is no time component here */
        OR (
            dt.d_value = CONVERT(DATE, '2016-07-01') 
            AND dt.t_value >= CONVERT(TIME(0), '11:00:00')
        )
    

    Se você precisar separar o componente de tempo para fins de análise , considere adicionar uma coluna calculada e persistente para a parte de tempo do valor:

    ALTER TABLE #DT
    ADD dt_value_time AS CONVERT(TIME(0), dt_value) PERSISTED;
    
    SELECT *
    FROM #dt;
    

    insira a descrição da imagem aqui

    A coluna persistente pode ser indexada permitindo classificações rápidas, etc., por hora do dia.

    Se você está pensando em dividir a data e hora em dois campos para fins de exibição, você deve perceber que a formatação deve ser feita no cliente, não no servidor.

    • 26
  2. JBentley
    2016-09-22T08:58:50+08:002016-09-22T08:58:50+08:00

    Vou fornecer uma opinião divergente para as outras respostas.

    Se os componentes de data e hora forem necessários juntos, ou seja, uma entrada é inválida se contiver um, mas não o outro (ou for NULL em um, mas não no outro), armazená-lo em uma única coluna faz sentido pelas razões fornecidas em outros respostas.

    No entanto, pode acontecer que um ou ambos os componentes sejam individualmente opcionais. Nesse caso, seria incorreto armazená-lo em uma única coluna. Fazer isso forçaria você a representar valores NULL de forma arbitrária, por exemplo, armazenando a hora como 00:00:00.

    Aqui estão alguns exemplos:

    • Você está registrando as viagens do veículo para deduções do imposto de milhagem. Saber a hora exata da viagem seria útil, mas se um funcionário não anotou e esqueceu, a data ainda deve ser registrada por si mesma (data obrigatória, hora opcional).

    • Você está realizando uma pesquisa para descobrir a que horas as pessoas almoçam e pede aos participantes que preencham um formulário com uma amostra de seus horários de almoço, incluindo datas. Alguns não se preocupam em preencher a data e você não deseja descartar os dados, pois são os horários que realmente importam (data opcional, hora obrigatória).

    Veja esta pergunta relacionada para abordagens alternativas.

    • 11
  3. Ashwini Mohan
    2016-09-21T06:39:55+08:002016-09-21T06:39:55+08:00

    Prefiro sempre armazenar isso como uma única coluna, a menos que haja alguma demanda específica de negócios/aplicativos. Abaixo estão meus pontos -

    • Extrair a hora do carimbo de data/hora não é um problema
    • Por que adicionar uma coluna extra apenas por tempo, se podemos armazenar os dois juntos
    • Para evitar adicionar Data e Hora sempre que estiver consultando.
    • 5
  4. Vladimir Oselsky
    2016-09-21T07:20:17+08:002016-09-21T07:20:17+08:00

    No SQL Server é melhor armazenar DataTime como um campo. Se você criar um índice na coluna DataTime, ele poderá ser usado como pesquisa de data e como pesquisa de data e hora. Portanto, se você precisar limitar todos os registros que existem para a data específica, ainda poderá usar o índice sem precisar fazer nada de especial. Se você precisar consultar a parte do tempo, não poderá usar o mesmo índice e, portanto, se tiver um caso de negócios em que se preocupa mais com a hora do dia do que com DateTime, armazene-o separadamente, pois precisará criar um índice sobre ele e melhorar o desempenho.

    • 3
  5. Ivan
    2016-09-21T09:55:38+08:002016-09-21T09:55:38+08:00

    De fato, é uma pena que não exista um tipo padrão de cross-DBMS para isso (como INT e VARCHAR são para inteiros e valores de string). As duas abordagens de banco de dados cruzadas que encontrei até agora estão usando colunas VARCHAR/CHAR para armazenar valores DataTime como strings formatadas de acordo com o padrão ISO 8601 (mais conveniente, legível por humanos) e usando BIGINT para armazená-los como carimbos de data e hora POSIX (armazenados mais eficiente, mais rápido, mais fácil de manipular matematicamente).

    • 1
  6. Arthur Tarasov
    2018-02-25T23:34:18+08:002018-02-25T23:34:18+08:00

    Depois de ler um monte de coisas, o horário UTC Unix no BIGINT parece ser a solução ideal. TZDB timesone ID em VARCHAR para armazenamento de fuso horário, se necessário. Alguns argumentos:

    1. TIMESTAMP e DATETIME fazem um monte de conversões enigmáticas em segundo plano que parecem ser complexas e não claras. O servidor alterna da hora local para UTC ou para a hora do servidor e vice-versa, às vezes ou não. Um monte de sobrecarga escondida para cada função.

    2. BIGINT (8kb) é pelo menos tão leve ou mais leve que DECIMAL necessário para armazenamento no formato xxxxxx.xxxxxx, que é praticamente armazenado como dois INTs + algo pelo MySQL . E é o suficiente para armazenar séculos à frente.

    3. Praticamente todas as principais linguagens de programação têm bibliotecas de funções padrão para trabalhar com o tempo Unix.

    4. As operações matemáticas com BIGINT devem ser tão rápidas ou mais rápidas do que qualquer outra coisa em qualquer hardware.

    Claro que todos os itens acima são relevantes para grandes projetos internacionais. Para algo pequeno, ir com o formato padrão do framework escolhido parece ser bom o suficiente.

    • 1

relate perguntas

  • Os índices filtrados podem ajudar a melhorar as consultas baseadas em uma hora inserida ou isso deve ser evitado?

  • Qual é a diferença entre os tipos de dados MySQL VARCHAR e TEXT?

  • É melhor armazenar os valores calculados ou recalculá-los a pedido? [duplicado]

  • Armazenar vs calcular valores agregados

  • Quais são algumas maneiras de implementar um relacionamento muitos-para-muitos em um data warehouse?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve