sql >> Database teknologi >  >> RDS >> Mysql

Mysql:Gem matrix af data i en enkelt kolonne

For det første vil du virkelig ikke gøre det. En søjle i et RDBMS er beregnet til at være atomisk, idet den indeholder én og kun én information. At forsøge at gemme mere end ét stykke data i en kolonne er en krænkelse af den første normale form.

Hvis du absolut skal gøre det, så skal du konvertere dataene til en form, der kan gemmes som et enkelt dataelement, typisk en streng. Du kan bruge PHP's serialize()-mekanisme, XML-parsing (hvis dataene tilfældigvis er et dokumenttræ), json_encode() osv.

Men hvordan forespørger du sådanne data effektivt? Svaret er, at du ikke kan.

Også, hvis en anden overtager dit projekt på et senere tidspunkt, vil du virkelig irritere dem, fordi serialiserede data i en database er forfærdelige at arbejde med. Jeg ved det, fordi jeg har arvet sådanne projekter.

Fik jeg nævnt, at du virkelig ikke vil gøre det? Du skal nytænke dit design, så det nemmere kan opbevares i form af atomrækker. Brug en anden tabel til disse data, for eksempel, og brug fremmednøgler til at relatere den til masterposten. De kaldes relationelle databaser af en grund.

OPDATERING :Jeg er blevet spurgt om krav til datalagring, som om en enkelt række ville være billigere med hensyn til lagring. Svaret er, i typiske tilfælde er det ikke det, og i tilfælde hvor svaret er ja, er prisen du betaler for det ikke værd at betale.

Hvis du bruger en 2 kolonneafhængig tabel (1 kolonne for fremmednøgle for den post, som prøven tilhører, en for en enkelt prøve), vil hver kolonne i værste fald kræve 16 bytes (8 bytes for en longint nøglekolonne, 8 bytes for et flydende kommatal med dobbelt præcision). For 100 poster er det 1600 bytes (ignorerer db overhead).

For en serialiseret streng gemmer du i bedste fald 1 byte pr. tegn i strengen. Du kan ikke vide, hvor lang strengen kommer til at være, men hvis vi antager, at 100 samples med alle de lagrede data ved en eller anden konstrueret tilfældighed alle falder mellem 10000,00 og 99999,99, hvor der kun er 2 cifre efter decimaltegnet, så ser på 8 bytes pr. prøve. I dette tilfælde er alt, hvad du har gemt, overheaden af ​​fremmednøglerne, så mængden af ​​krævet lagerplads kommer ud på 800 bytes.

Det er selvfølgelig baseret på en masse antagelser, såsom at tegnkodningen altid er 1 byte pr. tegn, strengene, der udgør samplerne, aldrig er længere end 8 tegn osv.

Men der er selvfølgelig også overhead af hvilken som helst mekanisme du bruger til at serialisere dataene. Den absolut enkleste metode, CSV, betyder at tilføje et komma mellem hver prøve. Det tilføjer n-1 bytes til den lagrede streng. Så ovenstående eksempel ville nu være 899 bytes, og det er med det enkleste kodningsskema. JSON, XML, selv PHP-serialiseringer tilføjer alle flere overhead-tegn end dette, og du vil snart have strenge, der er meget længere end 1600 bytes. Og alt dette er med antagelsen om 1 byte tegnkodning.

Hvis du har brug for at indeksere prøverne, vil datakravene vokse endnu mere uforholdsmæssigt i forhold til strenge, fordi et strengindeks er meget dyrere med hensyn til lagring, end et floating-point kolonneindeks ville være.

Og selvfølgelig, hvis dine prøver begynder at tilføje flere cifre, går datalagringen yderligere op. 39281.3392810 kan ikke lagres i 8 bytes som en streng, selv i det bedste tilfælde.

Og hvis dataene serialiseres, kan databasen ikke manipulere. Du kan ikke sortere prøverne, lave nogen form for matematiske operationer på dem, databasen ved ikke engang, at de er tal!

For at være ærlig er opbevaring dog latterligt billig i disse dage, du kan købe flere TB-drev for små summer. Er opbevaring virkelig så kritisk? Medmindre du har hundredvis af millioner af optegnelser, så tvivler jeg på, at det er det.

Du vil måske tjekke en bog kaldet SQL Antipatterns



  1. Vil du returnere ID på INSERT?

  2. Sådan begrænser du resultater i T-SQL

  3. MySQL giver fluktuerende rækkeantal, når jeg forespørger efter skema?

  4. Brug regulære udtryk i JPA CriteriaBuilder