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

MySQL ydeevne:flere tabeller vs. indeks på enkelt tabel og partitioner

At lave 20.000 borde er en dårlig idé. Du skal bruge 40.000 borde inden længe, ​​og så mere.

Jeg kaldte dette syndrom Metadata Tribbles i min bog SQL-antimønstre . Du ser dette ske, hver gang du planlægger at oprette en "tabel pr. X" eller en "kolonne pr. X".

Dette forårsager virkelige ydeevneproblemer, når du har titusindvis af borde. Hver tabel kræver MySQL for at vedligeholde interne datastrukturer, filbeskrivelser, en dataordbog osv.

Der er også praktiske driftsmæssige konsekvenser. Vil du virkelig oprette et system, der kræver, at du opretter en ny tabel, hver gang en ny bruger tilmelder sig?

I stedet vil jeg anbefale, at du bruger MySQL-partitionering .

Her er et eksempel på opdeling af tabellen:

CREATE TABLE statistics (
  id INT AUTO_INCREMENT NOT NULL,
  user_id INT NOT NULL,
  PRIMARY KEY (id, user_id)
) PARTITION BY HASH(user_id) PARTITIONS 101;

Dette giver dig fordelen ved at definere én logisk tabel, mens du også deler tabellen op i mange fysiske tabeller for hurtigere adgang, når du forespørger efter en bestemt værdi af partitionsnøglen.

For eksempel, når du kører en forespørgsel som dit eksempel, får MySQL kun adgang til den korrekte partition, der indeholder det specifikke user_id:

mysql> EXPLAIN PARTITIONS SELECT * FROM statistics WHERE user_id = 1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: statistics
   partitions: p1    <--- this shows it touches only one partition 
         type: index
possible_keys: NULL
          key: PRIMARY
      key_len: 8
          ref: NULL
         rows: 2
        Extra: Using where; Using index

HASH-metoden til partitionering betyder, at rækkerne placeres i en partition med et modul af heltalspartitionsnøglen. Dette betyder, at mange user_id'er er knyttet til den samme partition, men hver partition vil kun have 1/Nth så mange rækker i gennemsnit (hvor N er antallet af partitioner). Og du definerer tabellen med et konstant antal partitioner, så du ikke behøver at udvide den, hver gang du får en ny bruger.

Du kan vælge et hvilket som helst antal partitioner op til 1024 (eller 8192 i MySQL 5.6), men nogle mennesker har rapporteret ydeevneproblemer, når de bliver så høje.

Det anbefales at bruge et primært antal partitioner. Hvis dine user_id-værdier følger et mønster (som f.eks. kun at bruge lige tal), hjælper brug af et primtal af partitioner med at fordele dataene mere jævnt.

Til dine spørgsmål i kommentarfeltet:

For HASH-partitionering, hvis du bruger 101 partitioner som jeg viser i eksemplet ovenfor, så har enhver given partition omkring 1% af dine rækker i gennemsnit. Du sagde, at din statistiktabel har 30 millioner rækker, så hvis du bruger denne partitionering, ville du kun have 300.000 rækker pr. partition. Det er meget nemmere for MySQL at læse igennem. Du kan (og bør) også bruge indekser -- hver partition vil have sit eget indeks, og det vil kun være 1 % så stort, som indekset på hele den upartitionerede tabel ville være.

Så svaret på, hvordan kan du bestemme et rimeligt antal partitioner er:hvor stor er hele din tabel, og hvor store vil du have, at partitionerne skal være i gennemsnit?

Antallet af partitioner behøver ikke nødvendigvis at vokse, hvis du bruger HASH-partitionering. Til sidst kan du have 30 milliarder rækker i alt, men jeg har fundet ud af, at når din datamængde vokser i størrelsesordener, kræver det alligevel en ny arkitektur. Hvis dine data bliver så store, har du sandsynligvis brug for sharding over flere servere samt opdeling i flere tabeller.

Når det er sagt, kan du ompartitionere en tabel med ALTER TABLE:

ALTER TABLE statistics PARTITION BY HASH(user_id) PARTITIONS 401;

Dette skal omstrukturere tabellen (som de fleste ændringer af ALTER TABLE), så forvent, at det tager et stykke tid.

Du ønsker måske at overvåge størrelsen af ​​data og indekser i partitioner:

SELECT table_schema, table_name, table_rows, data_length, index_length
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE partition_method IS NOT NULL;

Som med enhver tabel ønsker du, at den samlede størrelse af aktive indekser skal passe ind i din bufferpulje, for hvis MySQL skal bytte dele af indekser ind og ud af bufferpuljen under SELECT-forespørgsler, lider ydeevnen.

Hvis du bruger RANGE- eller LIST-partitionering, er det meget mere almindeligt at tilføje, slippe, flette og opdele partitioner. Se http://dev.mysql. com/doc/refman/5.6/da/partitioning-management-range-list.html

Jeg opfordrer dig til at læse manualsektionen om partitionering , og tjek også denne fine præsentation ud:Boost ydeevne Med MySQL 5.1-partitioner .



  1. TSQL PIVOT FLERE KOLONNER

  2. mysql vælg datoer inden for 30-dages interval

  3. FEJL 1366 (HY000):Forkert strengværdi:'\xF0\x9F\x98\x9C' for kolonne 'kommentar' i række 1

  4. Sådan opretter du begrænsning af fremmednøgle med ON UPDATE CASCADE i SQL Server - SQL Server / TSQL Tutorial Del 79