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 / 20759
Accepted
prototype
prototype
Asked: 2012-07-12 18:41:17 +0800 CST2012-07-12 18:41:17 +0800 CST 2012-07-12 18:41:17 +0800 CST

Existe um nome para esse esquema de banco de dados de valores-chave?

  • 772

Processamos um feed de dados de rotina de um cliente que acabou de refatorar seu banco de dados de um formulário que parece familiar (uma linha por entidade, uma coluna por atributo) para um que parece desconhecido para mim (uma linha por entidade por atributo):

Antes: uma coluna por atributo

ID   Ht_cm   wt_kg   Age_yr  ... 
1      190      82     43    ...
2      170      60     22    ...
3      205      90     51    ...

Depois: uma coluna para todos os atributos

ID    Metric   Value
 1     Ht_cm     190
 1     Wt_kg     82
 1     Age_yr    43
 1      ...
 2     Ht_cm     170
 2     Wt_kg     60
 2     Age_yr    22
 2     ...
 3     Ht_cm     205
 3     Wt_kg     90
 3     Age_yr    51
 3     ...

Existe um nome para essa estrutura de banco de dados? Quais são as vantagens relativas? A maneira antiga parece mais fácil de colocar restrições de validade em atributos específicos (não nulos, não negativos, etc.) e mais fácil de calcular médias. Mas posso ver como pode ser mais fácil adicionar novos atributos sem refatorar o banco de dados. Esta é uma forma padrão/preferida de estruturar dados?

database-design schema
  • 5 5 respostas
  • 13578 Views

5 respostas

  • Voted
  1. Best Answer
    Simon Righarts
    2012-07-12T19:57:54+08:002012-07-12T19:57:54+08:00

    Chama-se Entidade-Atributo-Valor (às vezes também 'pares nome-valor') e é um caso clássico de "um pino redondo em um buraco quadrado" quando as pessoas usam o padrão EAV em um banco de dados relacional.

    Aqui está uma lista de por que você não deve usar o EAV:

    • Você não pode usar tipos de dados. Não importa se o valor é uma data, um número ou dinheiro (decimal). Sempre será forçado a varchar. Isso pode ser qualquer coisa, desde um pequeno problema de desempenho até uma enorme dor de barriga (já teve que perseguir uma variação de um centavo em um relatório mensal de resumo?).
    • Você não pode (facilmente) impor restrições. Requer uma quantidade ridícula de código para impor "Todos precisam ter uma altura entre 0 e 3 metros" ou "A idade não deve ser nula e >= 0", em oposição às 1-2 linhas que cada uma dessas restrições seria em um sistema devidamente modelado.
    • Relacionado ao acima, você não pode garantir facilmente que obterá as informações necessárias para cada cliente (a idade pode estar faltando em um, o próximo pode estar sem a altura, etc.). Você pode fazer isso, mas é muito mais difícil do que SELECT height, weight, age FROM Client where height is null or weight is null.
    • Relacionado novamente, dados duplicados são muito mais difíceis de detectar (o que acontece se eles fornecerem duas idades para um cliente? Desfazer o EAV dos dados, conforme abaixo, fornecerá duas linhas de resultados se você tiver um atributo duplicado. Se um cliente tiver duas entradas separadas para dois atributos, você obterá quatro linhas da consulta abaixo).
    • Você nem pode garantir que os nomes dos atributos sejam consistentes. "Age_yr" pode se tornar "AGE_IN_YEARS" ou "age". (Reconhecidamente, isso é menos problemático quando você está recebendo uma extração do que quando as pessoas estão inserindo dados, mas ainda assim.)
    • Qualquer tipo de consulta não trivial é um desastre completo. Para relacionar um sistema EAV de três atributos para que você possa consultá-lo de maneira racional, são necessárias três junções da tabela EAV.

    Comparar:

    SELECT cID.ID AS [ID], cH.Value AS [Height], cW.Value AS [Weight], cA.Value AS [Age]
    FROM (SELECT DISTINCT ID FROM Client) cID 
          LEFT OUTER JOIN 
        Client cW ON cID.ID = cW.ID AND cW.Metric = "Wt_kg" 
          LEFT OUTER JOIN 
        Client cH ON cID.ID = cH.ID AND cW.Metric = "Ht_cm" 
          LEFT OUTER JOIN 
        Client cA ON cID.ID = cA.ID AND cW.Metric = "Age_yr"
    

    Para:

    SELECT c.ID, c.Ht_cm, c.Wt_kg, c.Age_yr
    FROM Client c
    

    Aqui está uma lista (muito curta) de quando você deve usar o EAV:

    • Quando não há absolutamente nenhuma maneira de contornar isso e você precisa oferecer suporte a dados sem esquema em seu banco de dados.
    • Quando você só precisa armazenar "coisas" e não espera precisar delas de uma forma mais estruturada. Cuidado, porém, o monstro chamado "mudança de requisitos".

    Sei que acabei de passar este post inteiro detalhando por que o EAV é uma péssima ideia na maioria dos casos - mas há alguns casos em que é necessário/inevitável. no entanto, na maioria das vezes (incluindo o exemplo acima), será muito mais trabalhoso do que compensador. Se você tiver um requisito para amplo suporte de entrada de dados do tipo EAV, deve procurar armazená-los em um sistema de valor-chave, por exemplo, Hadoop/HBase, CouchDB, MongoDB, Cassandra, BerkeleyDB.

    • 98
  2. Neil McGuigan
    2012-07-12T18:54:47+08:002012-07-12T18:54:47+08:00

    Valor do Atributo da Entidade (EAV)

    É considerado um antipadrão por muitos, inclusive eu.

    Aqui estão suas alternativas:

    1. usar herança de tabela de banco de dados

    2. usar dados XML e funções SQLXML

    3. use um banco de dados nosql, como HBase

    • 19
  3. Erwin Brandstetter
    2012-11-14T02:25:46+08:002012-11-14T02:25:46+08:00

    No PostgreSQL, uma forma muito boa de lidar com estruturas EAV é o módulo adicional hstore, disponível a partir da versão 8.4 ou posterior. O manual:

    Este módulo implementa o hstoretipo de dados para armazenar conjuntos de pares chave/valor dentro de um único valor PostgreSQL. Isso pode ser útil em vários cenários, como linhas com muitos atributos que raramente são examinados ou dados semiestruturados. Chaves e valores são simplesmente strings de texto.

    Requer o módulo adicional hstore. Ver:

    • Pares de chave-valor no PostgreSQL

    Desde o Postgres 9.2, há também o jsontipo e uma série de funcionalidades para acompanhá-lo (a maior parte adicionada com o 9.3 ).

    O Postgres 9.4 adiciona o tipo de dados "JSON binário" (muito superior) jsonb. Com opções avançadas de índice.

    • 17
  4. Melvin PRESSOUYRE
    2013-01-07T15:25:38+08:002013-01-07T15:25:38+08:00

    Engraçado ver como o modelo EAV db é criticado e até considerado um "anti-padrão" por alguns.

    No que me diz respeito, as principais desvantagens são:

    • A curva de aprendizado é mais íngreme se você entrar em um projeto que já começou a usar o EAV há algum tempo. De fato, as consultas são difíceis , pois você aumenta muito o número de junções (e tabelas) e, portanto, exigirá mais tempo para você entender. Basta dar uma olhada no projeto Magento e ver como o desenvolvedor externo ao projeto tem dificuldade em trabalhar no banco de dados, mas a documentação é bem sustentada.
    • Não é adequado para relatórios , se você precisar obter o número de pessoas cujo nome começa com "M" etc...

    No entanto, você definitivamente não deve descartar esta solução, e aqui está o porquê:

    • Simon falou sobre o monstro chamado "mudança de requisitos". Eu gosto dessa expressão :). E IMHO é exatamente por isso que o EAV pode ser um bom candidato, porque é adequado para "mudança" , pois você pode adicionar quantos atributos desejar com bastante facilidade. Claro que depende dos requisitos que estamos mudando. Se estamos falando de um negócio totalmente novo, é claro que você terá que revisar seu dataModel, mas o EAV oferece muita flexibilidade. Só porque pede mais rigor, não significa que seja menos interessante.
    • Também foi dito que "Você não pode usar tipos de dados". : Isso está errado . Você pode muito bem ter várias tabelas de valores , uma para cada tipo de dados. Em seguida, você deve especificar em sua tabela de atributos qual tipo de dataType é seu atributo. Na verdade, uma mistura de relacional/EAV clássico com relacionamento de classe oferece muito potencial interessante no projeto de banco de dados.
    • 11
  5. Taryn
    2012-12-25T14:24:00+08:002012-12-25T14:24:00+08:00

    Se você tiver um banco de dados que esteja usando a estrutura EAV, é possível consultar os dados de várias maneiras.

    A resposta de @ Simon já mostra como realizar uma consulta usando várias junções.

    Dados de amostra usados:

    CREATE TABLE yourtable ([ID] int, [Metric] varchar(6), [Value] int);
    
    INSERT INTO yourtable ([ID], [Metric], [Value])
    VALUES (1, 'Ht_cm', 190),
        (1, 'Wt_kg', 82),
        (1, 'Age_yr', 43),
        (2, 'Ht_cm', 170),
        (2, 'Wt_kg', 60),
        (2, 'Age_yr', 22),
        (3, 'Ht_cm', 205),
        (3, 'Wt_kg', 90),
        (3, 'Age_yr', 51);
    

    Se você estiver usando um RDBMS que tenha uma PIVOTfunção ( SQL Server 2005+ / Oracle 11g+ ), poderá consultar os dados da seguinte maneira:

    select id, Ht_cm, Wt_kg, Age_yr
    from
    (
      select id, metric, value
      from yourtable
    ) src
    pivot
    (
      max(value)
      for metric in (Ht_cm, Wt_kg, Age_yr)
    ) piv;
    

    Consulte SQL Fiddle com demonstração

    Se você não tiver acesso a uma PIVOTfunção, poderá usar uma função agregada com uma CASEinstrução para retornar os dados:

    select id,
      max(case when metric ='Ht_cm' then value else null end) Ht_cm,
      max(case when metric ='Wt_kg' then value else null end) Wt_kg,
      max(case when metric ='Age_yr' then value else null end) Age_yr
    from yourtable
    group by id
    

    Consulte SQL Fiddle com demonstração

    Ambas as consultas retornarão dados no resultado:

    | ID | HT_CM | WT_KG | AGE_YR |
    -------------------------------
    |  1 |   190 |    82 |     43 |
    |  2 |   170 |    60 |     22 |
    |  3 |   205 |    90 |     51 |
    
    • 10

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

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 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

    Como selecionar a primeira linha de cada grupo?

    • 6 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
    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
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +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
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +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