Mysql
 sql >> база данни >  >> RDS >> Mysql

Производителност на MySQL:множество таблици спрямо индекс на една таблица и дялове

Създаването на 20 000 таблици е лоша идея. Ще ви трябват 40 000 маси скоро и след това още.

Нарекох този синдром Метаданни Tribbles в моята книга SQL Antipatterns . Виждате това да се случва всеки път, когато планирате да създадете „таблица за X“ или „колона за X“.

Това причинява реални проблеми с производителността, когато имате десетки хиляди таблици. Всяка таблица изисква MySQL да поддържа вътрешни структури от данни, файлови дескриптори, речник на данни и т.н.

Има и практически оперативни последици. Наистина ли искате да създадете система, която изисква да създавате нова таблица всеки път, когато се регистрира нов потребител?

Вместо това бих ви препоръчал да използвате Разделяне на MySQL .

Ето пример за разделяне на таблицата:

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;

Това ви дава предимството да дефинирате една логическа таблица, като същевременно разделяте таблицата на много физически таблици за по-бърз достъп, когато правите заявка за конкретна стойност на ключа на дяла.

Например, когато стартирате заявка като вашия пример, MySQL има достъп само до правилния дял, съдържащ конкретния 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 методът на разделяне означава, че редовете се поставят в дял чрез модул на целочисления ключ на дял. Това означава, че много user_id се преобразуват в един и същ дял, но всеки дял ще има средно само 1/N-ти толкова редове (където N е броят на дяловете). И вие дефинирате таблицата с постоянен брой дялове, така че не е нужно да я разширявате всеки път, когато получите нов потребител.

Можете да изберете произволен брой дялове до 1024 (или 8192 в MySQL 5.6), но някои хора съобщават за проблеми с производителността, когато достигнат толкова високо.

Препоръчително е да използвате прост брой дялове. В случай че вашите стойности на user_id следват модел (като използване само на четни числа), използването на прост брой дялове помага да се разпределят данните по-равномерно.

Повторете въпросите си в коментар:

За HASH разделяне, ако използвате 101 дяла, както показвам в примера по-горе, тогава всеки даден дял има средно около 1% от вашите редове. Казахте, че вашата таблица със статистически данни има 30 милиона реда, така че ако използвате това разделяне, ще имате само 300 000 реда на дял. Това е много по-лесно за MySQL за четене. Можете (и трябва) да използвате и индекси – всеки дял ще има свой собствен индекс и той ще бъде само 1% по-голям, колкото би бил индексът на цялата неразделена таблица.

Така че отговорът на въпроса как можете да определите разумен брой дялове е:колко голяма е цялата ви таблица и колко големи искате средно да бъдат дяловете?

Броят на дяловете не трябва непременно да нараства, ако използвате HASH разделяне. В крайна сметка може да имате общо 30 милиарда реда, но открих, че когато обемът на вашите данни нарасне с порядък, това все пак изисква нова архитектура. Ако данните ви станат толкова големи, вероятно имате нужда от шардиране върху множество сървъри, както и разделяне на множество таблици.

Въпреки това можете да разделите отново таблица с ALTER TABLE:

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

Това трябва да преструктурира таблицата (както повечето промени в ALTER TABLE), така че очаквайте да отнеме известно време.

Може да искате да наблюдавате размера на данните и индексите в дяловете:

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

Както при всяка таблица, искате общият размер на активните индекси да се побере във вашия буферен пул, защото ако MySQL трябва да разменя части от индекси в и извън буферния пул по време на SELECT заявки, производителността страда.

Ако използвате разделяне RANGE или LIST, тогава добавянето, пускането, сливането и разделянето на дялове е много по-често. Вижте http://dev.mysql. com/doc/refman/5.6/en/partitioning-management-range-list.html

Насърчавам ви да прочетете ръчния раздел за разделянето на дялове , а също така вижте тази хубава презентация:Увеличете производителността С MySQL 5.1 дялове .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Откриване на заключени маси (заключени от LOCK TABLE)

  2. SQLite - ПОРЪЧАЙТЕ ПО RAND()

  3. генерира дни от период от време

  4. Стартирайте localhost на mac OS X Yosemite

  5. enum('yes', 'no') срещу tinyint - кой да използвам?