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

Средната дължина на реда е по-висока от възможната

  • Защото avg_row_length е data_length / rows .

data_length е по същество общият размер на таблицата на диска . Таблицата на InnoDB е повече от просто списък с редове. Така че има допълнителни разходи.

  • Защото един InnoDB ред е повече от данните.

Подобно на по-горе, всеки ред идва с малко режийни разходи. Така че това ще добави към размера на реда. Таблицата на InnoDB също не е просто списък с данни, натъпкани заедно. Има нужда от малко допълнително празно пространство, за да работи ефективно.

  • Защото нещата се съхраняват на дискове в блокове и тези блокове не винаги са пълни.

Дисковете съхраняват нещата обикновено в 4K, 8K или 16K блокове . Понякога нещата не се вписват идеално в тези блокове, така че можете да получите нещо празно пространство .

Както ще видим по-долу, MySQL ще разпредели таблицата на блокове. И ще разпредели много повече, отколкото е необходимо, за да избегне необходимостта от увеличаване на таблицата (което може да бъде бавно и да доведе до фрагментиране на диска което прави нещата още по-бавни).

За да илюстрираме това, нека започнем с празна таблица.

mysql> create table foo ( id smallint(5) unsigned NOT NULL );
mysql> select data_length, table_rows, avg_row_length from information_schema.tables where table_name = 'foo';
+-------------+------------+----------------+
| data_length | table_rows | avg_row_length |
+-------------+------------+----------------+
|       16384 |          0 |              0 |
+-------------+------------+----------------+

Той използва 16K или четири 4K блока, за да не съхранява нищо. Празната таблица не се нуждае от това пространство, но MySQL го разпредели с предположението, че ще поставите куп данни в нея. Това избягва необходимостта от скъпо преразпределяне на всяка вложка.

Сега нека добавим ред.

mysql> insert into foo (id) VALUES (1);
mysql> select data_length, table_rows, avg_row_length from information_schema.tables where table_name = 'foo';
+-------------+------------+----------------+
| data_length | table_rows | avg_row_length |
+-------------+------------+----------------+
|       16384 |          1 |          16384 |
+-------------+------------+----------------+

Масата не стана по-голяма, има цялото това неизползвано пространство в рамките на тези 4 блока, които има. Има един ред, който означава avg_row_length от 16K. Явно абсурдно. Нека добавим още един ред.

mysql> insert into foo (id) VALUES (1);
mysql> select data_length, table_rows, avg_row_length from information_schema.tables where table_name = 'foo';
+-------------+------------+----------------+
| data_length | table_rows | avg_row_length |
+-------------+------------+----------------+
|       16384 |          2 |           8192 |
+-------------+------------+----------------+

Същото нещо. 16K са разпределени за таблицата, 2 реда, използващи това пространство. Абсурден резултат от 8K на ред.

Докато вмъквам все повече и повече редове, размерът на таблицата остава същият, използва все повече и повече от разпределеното си пространство и avg_row_length се доближава до реалността.

mysql> select data_length, table_rows, avg_row_length from information_schema.tables where table_name = 'foo';                                                                     
+-------------+------------+----------------+
| data_length | table_rows | avg_row_length |
+-------------+------------+----------------+
|       16384 |       2047 |              8 |
+-------------+------------+----------------+

Тук също започваме да виждаме table_rows стават неточни. Определено вмъкнах 2048 реда.

Сега, когато вмъкна още...

mysql> select data_length, table_rows, avg_row_length from information_schema.tables where table_name = 'foo';
+-------------+------------+----------------+
| data_length | table_rows | avg_row_length |
+-------------+------------+----------------+
|       98304 |       2560 |             38 |
+-------------+------------+----------------+

(Вмъкнах 512 реда и table_rows се върна към реалността по някаква причина)

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

Той грабна много повече място, отколкото му е необходимо за тези 512 реда, сега е 96K или 24 4K блока, с допускането, че ще има нужда от него по-късно. Това свежда до минимум колко потенциално бавни преразпределения трябва да направи и свежда до минимум фрагментацията на диска.

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

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




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. mySQL:Използване на разстоянието на Левещайн за намиране на дубликати в 20 000 реда

  2. Django AWS RDS MySQL Грешка:(2026, „Грешка при SSL връзката:грешка:00000001:lib(0):func(0):причина(1)“)

  3. Интеграция на WordPress MediaWiki

  4. Mysql Подреждане по фамилно име, когато пълното име за колона

  5. Как да каскадно персистирате с помощта на JPA/EclipseLink