У меня есть таблица с ~ 6M строками, которая извлекает около 20 000-30 000 строк на запрос с оптимизацией индекса. Однако, так как многие люди последовательно извлекают эти строки (каждые 30 секунд или около того), сайт часто будет тайм-аутом для людей.
Недавно я перенес базу данных в 3-серверный кластер MySQL с огромным объемом оперативной памяти (512 ГБ на сервер), и производительность не улучшилась.
Мне было интересно, будет ли partioning лучшим способом для улучшения производительности. Поскольку у меня нет абсолютно никакого опыта общения с партией, я думал, что попрошу здесь.
Мой вопрос в том, что все эти строки имеют столбец, который либо будет иметь значение 0, 1, 2 или 3.
Можно ли каким-либо образом разместить все строки со значением 1 в определенном столбце на одном разделе, а все строки со значением 2 в столбце в другом? И будут ли они автоматически перемещаться в зависимости от значения, которое обновляется в первичной таблице? И самое главное, это могло бы помочь в производительности, поскольку ему нужно было бы только просмотреть 1 ряд в 20 000-30 000 вместо 6 000 000
Да, MySQL поддерживает разделение. Вы можете определить разделы очень хорошо, например:
CREATE TABLE MyTable (
id INT AUTO_INCREMENT PRIMARY KEY,
somestuff INT,
otherstuff VARCHAR(100),
KEY (somestuff)
) PARTITION BY HASH(id) PARTITIONS 4;
INSERT INTO MyTable () VALUES (), (), (), ();
Вы можете проверить количество строк в каждом разделе после этого:
SELECT PARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='MyTable';
+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| p0 | 1 |
| p1 | 1 |
| p2 | 1 |
| p3 | 1 |
+----------------+------------+
Тем не менее, есть две вещи, которые отключают людей, когда они пытаются использовать разбиение на разделы в MySQL:
Во-первых, https://dev.mysql.com/doc/refman/5.7/en/partitioning-limitations-partitioning-keys-unique-keys.html говорит:
каждый уникальный ключ в таблице должен использовать каждый столбец в выражении разбиения таблицы.
Это означает, что если вы хотите разделить на несколько somestuff
в приведенном выше примере, вы не сможете. Это не позволит требовать, чтобы первичный ключ включал столбец, названный в выражении раздела.
ALTER TABLE MyTable PARTITION BY HASH(somestuff) PARTITIONS 4;
ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table partitioning function
Вы можете обойти это, удалив из своей таблицы какие-либо первичные ключи или уникальные ограничения ключей, но это оставляет вас с некорректной таблицей.
Во-вторых, разделение ускоряет запросы только в том случае, если вы можете воспользоваться обрезкой разделов, и это происходит, только если ваши условия запроса включают столбец, используемый в выражении раздела.
mysql> EXPLAIN PARTITIONS SELECT * FROM MyTable WHERE SomeStuff = 3;
+----+-------------+---------+-------------+------+---------------+-----------+---------+-------+------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------------+------+---------------+-----------+---------+-------+------+-------+
| 1 | SIMPLE | MyTable | p0,p1,p2,p3 | ref | somestuff | somestuff | 5 | const | 4 | NULL |
+----+-------------+---------+-------------+------+---------------+-----------+---------+-------+------+-------+
Обратите внимание, что это потребует сканирования разделов p0, p1, p2, p3 - т.е. всей таблицы. Нет обрезки разделов, поэтому нет улучшения производительности, поскольку она не уменьшает количество проверенных строк.
Если вы выполняете поиск определенного значения в столбце, используемом в выражении секционирования, вы можете видеть, что MySQL может уменьшить количество просматриваемых разделов:
mysql> EXPLAIN PARTITIONS SELECT * FROM MyTable WHERE id = 3;
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | MyTable | p3 | const | PRIMARY | PRIMARY | 4 | const | 1 | NULL |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+-------+
Разделение может многое помочь в особых обстоятельствах, но разделение не так много, как думает большинство людей.
В большинстве случаев лучше определить более конкретные индексы в таблице для поддержки запросов, которые необходимо выполнить.
SHOW CREATE TABLE
.