Как оценить / предсказать размер данных и размер индекса таблицы в MySQL

26

Я нахожу, что это лучший способ оценить размер таблицы для этого я изучил много блогов и форумов, но не смог найти точного ответа

Например, у нас есть таблица City с движком InnoDB , скажем, в будущем (в течение следующего года) она будет иметь 1 миллион записей, так что это будет примерный размер данных и размер индекса этой таблицы в этот период.

mysql> desc City;
+-------------+----------+------+-----+---------+----------------+
| Field       | Type     | Null | Key | Default | Extra          |
+-------------+----------+------+-----+---------+----------------+
| ID          | int(11)  | NO   | PRI | NULL    | auto_increment |
| Name        | char(35) | NO   |     |         |                |
| CountryCode | char(3)  | NO   | MUL |         |                |
| District    | char(20) | NO   |     |         |                |
| Population  | int(11)  | NO   |     | 0       |                |
+-------------+----------+------+-----+---------+----------------+
5 rows in set (0.03 sec)

ОБНОВИТЬ

Какова будет оценочная верхняя граница (максимальный размер таблицы) с 1 миллионом записей и как мы можем ее оценить.

Абдул Манаф
источник
Это здорово. но возможно ли получить столбец размера индекса разумно. Что значит, если у вас есть таблица с (скажем) 5 столбцов проиндексированы. Можем ли мы получить размер индекса каждого из них? Я задам это как другой вопрос. спасибо
Сушил

Ответы:

51

Учитывая описание таблицы, я вижу

  • 66 байт на строку данных
  • 4 байта в строке для первичного ключа
  • 7 байтов в строке для индекса кода страны
    • 3 байта для страны
    • 4 байта для кластерного ключа, прикрепленного к коду страны
  • Всего 77 байтов данных и ключей
  • Это не учитывает ведение домашнего хозяйства для BTREEs или фрагментацию табличного пространства

Для миллиона строк это будет 77 000 000 байтов (73,43 МБ)

Что касается измерения таблицы, для данной таблицы mydb.mytable вы можете выполнить этот запрос

SELECT 
    CONCAT(FORMAT(DAT/POWER(1024,pw1),2),' ',SUBSTR(units,pw1*2+1,2)) DATSIZE,
    CONCAT(FORMAT(NDX/POWER(1024,pw2),2),' ',SUBSTR(units,pw2*2+1,2)) NDXSIZE,
    CONCAT(FORMAT(TBL/POWER(1024,pw3),2),' ',SUBSTR(units,pw3*2+1,2)) TBLSIZE
FROM
(
    SELECT DAT,NDX,TBL,IF(px>4,4,px) pw1,IF(py>4,4,py) pw2,IF(pz>4,4,pz) pw3
    FROM 
    (
        SELECT data_length DAT,index_length NDX,data_length+index_length TBL,
        FLOOR(LOG(IF(data_length=0,1,data_length))/LOG(1024)) px,
        FLOOR(LOG(IF(index_length=0,1,index_length))/LOG(1024)) py,
        FLOOR(LOG(data_length+index_length)/LOG(1024)) pz
        FROM information_schema.tables
        WHERE table_schema='mydb'
        AND table_name='mytable'
    ) AA
) A,(SELECT 'B KBMBGBTB' units) B;

Чтобы измерить все таблицы, сгруппированные по базам данных и хранилищу

SELECT
    IF(ISNULL(DB)+ISNULL(ENGINE)=2,'Database Total',
    CONCAT(DB,' ',IFNULL(ENGINE,'Total'))) "Reported Statistic",
    LPAD(CONCAT(FORMAT(DAT/POWER(1024,pw1),2),' ',
    SUBSTR(units,pw1*2+1,2)),17,' ') "Data Size",
    LPAD(CONCAT(FORMAT(NDX/POWER(1024,pw2),2),' ',
    SUBSTR(units,pw2*2+1,2)),17,' ') "Index Size",
    LPAD(CONCAT(FORMAT(TBL/POWER(1024,pw3),2),' ',
    SUBSTR(units,pw3*2+1,2)),17,' ') "Total Size"
FROM
(
    SELECT DB,ENGINE,DAT,NDX,TBL,
    IF(px>4,4,px) pw1,IF(py>4,4,py) pw2,IF(pz>4,4,pz) pw3
    FROM 
    (SELECT *,
        FLOOR(LOG(IF(DAT=0,1,DAT))/LOG(1024)) px,
        FLOOR(LOG(IF(NDX=0,1,NDX))/LOG(1024)) py,
        FLOOR(LOG(IF(TBL=0,1,TBL))/LOG(1024)) pz
    FROM
    (SELECT
        DB,ENGINE,
        SUM(data_length) DAT,
        SUM(index_length) NDX,
        SUM(data_length+index_length) TBL
    FROM
    (
       SELECT table_schema DB,ENGINE,data_length,index_length FROM
       information_schema.tables WHERE table_schema NOT IN
       ('information_schema','performance_schema','mysql')
       AND ENGINE IS NOT NULL
    ) AAA GROUP BY DB,ENGINE WITH ROLLUP
) AAA) AA) A,(SELECT ' BKBMBGBTB' units) B;

Запустите эти запросы, и вы сможете отслеживать изменения в использовании диска базы данных / движка.

Попробуйте!

RolandoMySQLDBA
источник
1
Это действительно отличный запрос для просмотра таблиц всех размеров.
Гэйс
Эти CHARдлины должны быть умножены на 3 , если у вас есть CHARSET utf8. Все накладные расходы можно оценить, удвоив или утроив вычисление.
Рик Джеймс
@RolandoMySQLDBA, знаете ли вы, возможно ли рассчитать «реальный» размер строки таблицы с целью сравнить ее с реальным размером (сжатая таблица) и получить коэффициент сжатия?
Ceinmart
@ceinmart innodb_page_size фиксирован (16K или 16384 по умолчанию) и становится границей, где строки и сгруппированы или разделены. Изменение innodb_page_size может изменить хранение данных, хорошее или плохое. На основании того, насколько заполнена или разрежена строка (особенно при наличии TEXT / BLOB / VARCHAR). В лучшем случае вы должны сравнить размер файла .ibd с тем, что указано в отчете схемы, чтобы оценить соотношение. Вам также может понадобиться выполнить NULL ALTER TABLE ( ALTER TABLE ... ENGINE=InnoDB;), чтобы получить точное соотношение. Усилие может не стоить того.
RolandoMySQLDBA
@ceinmart Имейте в виду, что изменение innodb_page_size не является настройкой таблицы за таблицей. Вам необходимо выполнить полный экспорт данных (см. Mariadb.com/kb/en/library/how-to-change-innodb_page_size )
RolandoMySQLDBA
4

Если вы используете таблицы InnoDB, вы можете получить размер для данных / отдельных индексов mysql.innodb_index_stats. Статистика «size» содержит ответ в страницах, поэтому его необходимо умножить на размер страницы, то есть по умолчанию 16K .

select database_name, table_name, index_name, stat_value*@@innodb_page_size
from mysql.innodb_index_stats where stat_name='size';

Индекс PRIMARY - это сами данные.

Вайк Хермеч
источник
1
Это предполагает, что у вас есть данные в таблице; Похоже, что ОП хочет оценить перед заполнением.
Рик Джеймс
0
SELECT  Table_NAME "tablename",
           data_length   "table data_length in Bytes",
           index_length  "table index_length in Bytes",
           data_free  "Free Space in Bytes"
    FROM  information_schema.TABLES  where  Table_schema = 'databasename';

выполнив этот запрос, вы можете получить размер, используемый для Dataи Indexтаблицы, вы можете проверить этот размер по количеству строк и прогнозировать 1 миллион строк

Петер Вендерберге
источник
1
Я не уверен, но даст ли это какие-то точные результаты? Вы проверяли это когда-либо?
Абдул Манаф
На самом деле я периодически проверяю этот результат запроса, чтобы увидеть рост (%) по отношению к размеру
Питер Вендерберге
0

Если у вас еще нет данных, вот несколько советов. Следующее относится к InnoDB. (MyISAM намного проще и меньше.)

Не используйте CHARдля столбцов переменной длины. Что CHARACTER SETвы используете? Ascii нужен один байт на символ; utf8mb4 нужно от 1 до 4.

4 bytes per INT
35 for CHAR(35), if ascii or latin1; varchar is probably less
3 for the country code; it is fixed length
etc

Всего = около 80 байтов.

Умножьте 80 на 2 или 3, чтобы учесть различные накладные расходы. Скорее всего, таблица строк 1М будет между 160 и 240 МБ.

Чтобы измерить один индекс, скажем, CountryCodeиз 3 байтов:

3 bytes data
4 bytes for the PK (implicitly included with any secondary key)
25 bytes basic overhead
32 total
times 1.5 -- overhead for BTree that was randomly inserted into
48MB -- total for 1M rows.

Заметки:

  • Только листовые узлы (из BTrees) должны быть вычислены; накладные расходы для неконечных узлов обычно составляют 1%.

  • Данные PRIMARY KEY«кластеризованы» с данными, поэтому нет необходимости вычислять их.

  • Если у вас нет явного PK, то вам нужно добавить 6 байтов к размеру строки, чтобы учесть изготовленное PK.

  • ROW_FORMAT = COMPRESSEDдает усадку 2: 1. (Это не так хорошо, как типичная степень сжатия zip (и т. Д.) 3: 1.)

  • SHOW TABLE STATUS LIKE "tablename";это быстрый способ вычислить «фактический» размер. Смотрите Data_lengthдля данных и ПК; Index_lengthдля вторичных индексов и Data_freeдля некоторых других вещей.

  • Это редко для того, Index_lengthчтобы превзойти Data_length. Однако это не «неправильно», чтобы это произошло.

Рик Джеймс
источник
-1

Это утомительно. Но подробности в документах .

Чтобы быть настолько точным, насколько это возможно, что редко требуется, вам нужно прочитать также о структуре таблицы и структуре индекса.

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

Майк Шеррилл 'Cat Recall'
источник