Durante nossa última reunião semanal, uma pessoa que não tem experiência em administração de banco de dados levantou esta questão:
"Haveria um cenário que justificasse o armazenamento de dados em linha (string) em vez de várias linhas?"
Vamos assumir uma tabela chamada countryStates
onde queremos armazenar os estados de um país; Usarei os EUA neste exemplo e não listarei todos os Estados por preguiça.
Lá teríamos duas colunas; um chamado Country
e o outro chamado States
. Conforme discutido aqui e proposto pela resposta de @ srutzky , PK
será o código definido pela ISO 3166-1 alfa-3 .
Nossa tabela ficaria assim:
+---------+-----------------------+-------------------------------------------------------+
| Country | States | StateName |
+---------+-----------------------+-------------------------------------------------------+
| USA | AL, CA, FL,OH, NY, WY | Alabama, California, Florida, Ohio, New York, Wyoming |
+---------+-----------------------+-------------------------------------------------------+
Ao fazer a mesma pergunta a um desenvolvedor amigo, ele disse que, do ponto de vista do tamanho do tráfego de dados, isso pode ser útil, mas não se precisarmos manipular esses dados. Nesse caso, teria que haver uma inteligência no código do aplicativo que poderia transformar essa string em uma lista (digamos que o software que tem acesso a esta tabela precise criar uma caixa de combinação).
Concluímos que esse modelo não é muito útil, mas suspeitei que pudesse haver uma maneira de torná-lo útil.
O que eu gostaria de perguntar é se algum de vocês já viu, ouviu ou fez algo assim de uma maneira que realmente funciona .
fonte
a;b;c
, use o front end para analisar sua string ea
, em seguidab
,c
execute a execução fazendo algo com eles, talvez? Sinta que pode atender a algum tipo de necessidade específica dessa maneira ... Pensando bem, não. Você sempre pode armazenar IDs, Junte-se a suas tabelas e criar uma string concatenada que pode enviar conteúdo para o FE ...Respostas:
Para começar, o título da pergunta atual referente a "armazenamento de dados como string em vez de colunas" é um pouco confuso. Quando se fala em armazenar dados como cadeias de caracteres em vez de outra coisa, isso geralmente se refere à serialização de tudo para um formato de cadeia de caracteres, em vez de um tipo de dados adequado / forte (por exemplo,
INT
ouDATETIME
). Mas se perguntar sobre o armazenamento de dados como vários valores em um único campo, em vez de separar linhas, isso é um pouco diferente. E para ser justo, embora a concatenação de valores seja mais facilmente feita com strings, também pode ser feita comINT
eBINARY
tipos, mascarando bits ou reservando da mesma forma determinadas posições para ter significados diferentes. Como a segunda interpretação é sobre o que realmente está sendo perguntado, com base no texto da pergunta, vamos abordar isso.Em uma palavra: Não. Se você estiver armazenando pontos de dados reais, isso trará apenas dor (em termos de código e desempenho), pois é uma complicação desnecessária. Se for um valor que só será armazenado como uma única unidade, atualizado como uma única unidade e nunca desmontado no banco de dados, isso pode ser aceitável, pois é aproximadamente análogo ao armazenamento de uma imagem ou PDF. Caso contrário, qualquer tentativa de analisar os dados invalidará o uso de quaisquer índices (por exemplo
LIKE '%something%'
, usando , ouCHARINDEX
, ouPATINDEX
, ouSUBSTRING
, etc).Se você precisar armazenar valores separados em um único campo de uma única linha, haverá meios mais apropriados de fazer isso: XML ou JSON. Esses são formatos analisáveis ( XML / JSON ) e o XML pode até ser indexado . Mas, idealmente, esses dados seriam armazenados em campos digitados corretamente, para que possam ser realmente úteis.
E não se esqueça de que o objetivo de um RDBMS é armazenar dados para que possam ser recuperados e manipulados da maneira mais eficiente possível, dentro das restrições impostas por ser compatível com ACID . A recuperação de valores concatenados é ruim o suficiente devido à necessidade de analisar os valores primeiro e isso não é indexável. Mas manipular geralmente significa substituir o blob inteiro apenas para atualizar uma parte dele (assumindo que não existe um padrão para usar com uma
REPLACE
função). O tipo de dados XML pelo menos permite XML DML para atualizações simplistas, embora elas ainda não sejam tão rápidas quanto uma simples atualização de dados modelados corretamente.Além disso, dado um cenário como o que é mostrado na pergunta acima, concatenando todos os códigos de estado juntos, você não conseguiria Chave estrangeira (em qualquer direção) desses valores.
E se os requisitos de negócios mudarem com o tempo e você precisar rastrear propriedades adicionais desses itens? Em termos de "estados", o que dizer das capitais, população ou ordem de classificação ou qualquer outra coisa? Armazenado corretamente como linhas, você pode adicionar mais colunas para propriedades adicionais. Claro, você pode ter vários níveis de dados analisáveis, como,
|StateCode,Capital,Population |StateCode,Capital,Populate|...
espero, que qualquer pessoa possa ver o problema ficando exponencialmente fora de controle. Obviamente, esse problema em particular é facilmente tratado com os formatos XML e JSON, e esse é o valor deles, como mencionado acima. Mas você ainda precisa de uma muito boa razão para usar qualquer um desses como meios iniciais de modelagem como nem nunca vai ser tão eficiente quanto usar campos discretos em linhas separadas.fonte
Na verdade, usei algo assim para um propósito muito limitado. Criamos uma tabela de cabeçalhos para arquivos de saída. Eles foram construídos especificamente e eram principalmente apenas os títulos das colunas, mas não exatamente. Então os dados pareciam algo como
Essencialmente, parecia que era uma lista delimitada. E de uma maneira que era. Mas, para nossos propósitos, era uma única corda longa.
Esse é o truque aqui. Se você nunca planeja analisar a lista, vale a pena salvá-la. Se, no entanto, você precisar ou precisar analisar a lista, vale a pena o espaço e o tempo extra para dividi-la e salvá-la em linhas separadas.
fonte
Eu usei uma vez com uma tabela bastante pequena, por exemplo:
E então armazene valores
CRM,SMS,SELF-CARE
emvalid_channel
.A tabela inteira tem algo como 10 registros.
valid_channel
contém valores que realmente devem estar em uma tabela de vínculo que representa o relacionamento muitos-para-muitos. A mesat1
não será usada intensivamente, por isso decidimos seguir esse caminho. Algumas políticas estavam envolvidas nessa decisão, no entanto (veja abaixo).Mas, em geral, eu evito, não é 3NF.
O local em que trabalho atualmente tem dezenas dessas colunas por todo o lugar. A justificativa deles é que isso facilita as consultas: em vez de juntar três tabelas usando a tabela de vinculação, elas podem ir direto para a tabela de definição usando
LIKE
. Por exemploHorrível + no Oracle, desativa o uso do índice por causa do início
'%,'
.fonte
LIKE
ou uma junção simples?LIKE
seria mais lento, especialmente se os dados forem modelados corretamente para usar umTINYINT
campo PK emchannel_def
. Então, ele só precisa comparar um único byte entre as duas tabelas. Aqui, ele deve analisar a sequência, caractere por caractere (pelo menos até que a condição seja satisfeita), e está fazendo uma pesquisa que não diferencia maiúsculas de minúsculas (com base na definição de tabela especificada que não mostra um_BIN2
agrupamento sendo usado). Isso invalida índices no SQL Server também. Eu resolvi isso na minha resposta dizendo que a análise não pode usar índices. Acabei de atualizar minha resposta para torná-la mais clara.LIKE
cláusula e produzam resultados estranhos, ainda podem causar outros problemas ou pelo menos dificultar / depurar mais a depuração). Isso também torna a atualização dovalid_channels
campo mais complicada. Isso não quer dizer que isso não funcione, simplesmente não há uma boa razão para fazê-lo.Isso foi feito aqui no SE. Como Marc Gravell escreve :
Esse "novo formato" foi o próximo passo do "formato antigo", que era um pouco diferente e foi escolhido para usar o recurso de Pesquisa de Texto Completo do SQL Server, portanto, alguns dos benefícios não são relevantes se você o fizer do zero.
Presumivelmente, eles não normalizaram completamente a coisa por razões de quantidade de trabalho e desempenho.
fonte
Bem, um possível benefício principal do uso de seqüências de caracteres e outros tipos de dados é enviá-los do SQL Server para C #, C, C ++ (etc) usando o SQLCLR quando é necessário um desempenho absoluto. Você pode até criar uma exibição ou procedimento armazenado para representar dados relacionais de maneira não relacional - como no exemplo acima, com esse objetivo.
Veja este exemplo:
http://aboutsqlserver.com/2013/07/22/clr-vs-t-sql-performance-considerations/
por Wikipedia: SQL CLR ou SQLCLR (SQL Common Language Runtime) é uma tecnologia para hospedagem do mecanismo de tempo de execução de linguagem comum do Microsoft .NET no SQL Server. O SQLCLR permite que o código gerenciado seja hospedado e executado no ambiente do Microsoft SQL Server.
fonte
Na minha opinião, a resposta seria não. Eu não usei essa abordagem e a evitaria - não consigo pensar em uma razão para seguir esse caminho. Você está se inclinando para o mundo do JSON / NoSQL com uma matriz.
Tínhamos opções de design semelhantes em uma função anterior, na qual a equipe de arquitetos queria ter um campo "Dados" que fosse delimitado e depois convertido em binário. No final, não seguimos esse caminho por alguns motivos.
Se você tivesse que ingressar nesse tipo de dados, seria uma experiência feia. A atualização de elementos únicos da sequência também seria desagradável.
fonte