Задавайте вопросы, мы ответим
Вы не зашли.
В версии MySql5.1 появилась возможность разбивать таблицу на партиции.
Реально много прогуглил, но подробного разбора этой темы не нашел - просто обзоры с общими фразами.
На родном сайте в принципе написано, но нюансы из-за моего не глубокого знания MySql я не понял.
У меня порядка ста (пока) таблиц с прайсами по 1-2,5млн строк.
Индексируется по одному полю - артикулу. Индекс не уникальный - могут быть повторения.
Поиск при каждом запросе ведется по всем ста таблицам по этому полю через UNION еще и с LEFT JOIN.
Хочу с помощью разбиения на партиции ускорить поиск.
Разбиение по RANGE и LIST понятно. Не понял как будут разбиваться таблицы при использовании HASH и KEY.
И как будет вестись поиск по этим разбитым таблицам.
К примеру:
если использовать BY KEY то будет задействована одна партиция где искомый артикул или все?
Чем отличаются BY KEY и BY LINEAR KEY?
На сколько я понял разбиение горизонтальное - как это может ускорить поиск?
Большая просьба разжевать тему разбиения BY HASH, BY LINEAR HASH, BY KEY и BY LINEAR KEY
или дать ссылку где это разжевано с примерами.
Заранее спасибо.
Неактивен
Все эти четыре разбиения достаточно похожи друг на друга, это факт. Для того, чтобы понять,
как оно будет разбиваться, нужно оторваться от значений слов HASH и KEY в том понимании,
как они используются обычно.
1. Начнем с HASH. Hash нужно в данном случае понимать не как привычный нам хэш (типа md5),
а как математическую функцию, которая берет число на входе и получает какое-то другое число
на выходе. Самый примитивный способ — на выходе то же самое число, что и на входе. Выбор
раздела при этом происходит путем вычисления остатка от деления этого числа на количество
разделов. Звучит несколько запутанно, поэтому пример.
Вставляем строки в таблицу из двух разделов с хэш-разбиением. Вставляем строку 1. Остаток
от деления 1 на 2 — 1, поэтому строка попадает в 1 раздел. Вторая строка — по аналогии, во второй.
Третья — опять в первый (3 % 2 = 1). Четвертая — во второй. И так далее.
Т.е. при равномерном увеличении числа на 1 мы получаем, что строки равномерно попадают в два
раздела. Если числа будут увеличиваться другим способом — разбиение может быть менее
качественным (например, 1,3,5,.. — будут попадать всегда в один раздел).
В HASH можно использовать какие-то выражения (до взятия остатка от деления). Например, если
у Вас в таблице хранятся числа от 0 до 1, и Вы хотите разбивать таблицу на 2 раздела, то можно взять
хэширующую функцию field * 2 (или field * 100), тогда при округлении до целого числа (для вычисления
модуля) MySQL будет получать не только ноль, но и другие числа.
2. LINEAR HASH. Наверное, не очень удачное название, но уж как есть. Отличие от обычного хэша в том,
что вычисление номера раздела по числу хэш-функции — не взятие модуля, а более сложный алгоритм:
F() & (POWER(2, CEILING(LOG(2, num))) - 1).
Насколько удачно такое решение — не известно, но утверждается, что в таком случае гораздо проще
добавлять-удалять разделы (т.к. используются степени двойки, обычно делится только один из разделов).
С другой стороны, теряется равномерность.
3. KEY. Если все понятно с HASH, то с KEY все еще проще — тут искусственно навязывается встроенный
алгоритм хэширования. Сделано это для того, чтобы можно было разбивать таблицу не только по числовому
полю, но, например, по строковому. На алгоритм никак повлиять нельзя, он всегда фиксированный.
4. LINEAR KEY. Аналогично пунктам 2 и 3 — фиксированный алгоритм хэширования + выбор раздела не остатком
от деления, а линейным двоичным алгоритмом.
--
Что касается «ускорения поиска». Единственный способ ускорить поиск разбиением — не читать не
затрагиваемые разделы. PRUNING будет работать на этих видах разбиения только в случае точечных
запросов с WHERE по указанному полю (например, WHERE field = 1). В любых других случаях, MySQL
не сможет оценить, какие разделы будут затронуты, и прийдется обработать все из них.
Неактивен
Реальное спасибо за ответ.
Тогда следующий вопрос:
выдержка с оф.сайта:
CREATE TABLE t4 (
fname VARCHAR(50) NOT NULL,
lname VARCHAR(50) NOT NULL,
region_code TINYINT UNSIGNED NOT NULL,
dob DATE NOT NULL
)
PARTITION BY KEY(region_code)
PARTITIONS 8;
Any query such as this one can be pruned:
SELECT * FROM t4 WHERE region_code = 7;
... а если не PARTITION BY KEY(region_code) - поле с целыми числами, а PARTITION BY KEY(fname) ,
т.е. значения в поле текстово-цифровые (VARCHAR) и запрос соответственно (for ex.):
SELECT * FROM t4 WHERE fname = 'JOHN';
сработает ли так называемое сокращение запроса (т.е. будет читаться именно та партиция)?
Неактивен
Да, разумеется. Главное, чтобы было понятно, из какого раздела тянуть, на этапе работы
оптимизатора. Т.к. оптимизатор может посчитать KEY('JOHN'), он может определить, из какого
раздела вытянуть данные. Как следствие, будет читаться только этот раздел.
Неактивен
За статью спасибо, все просто и понятно.
Скажите, а есть ли возможность на "физическом" уровне удалять партиции, а потом, при необходимости, подкладывать обратно?
Например, если логи разбиты на партиции, по дате, и занимают большое количество места на диске, то можно ли вырезать с данного сервера партиции со старыми логами, а в будущем, если понадобятся логи за определённый день - вернуть назад партицию на сервер ?
Неактивен
Хорошего способа нет, но, например, если Вы используете MyISAM, можете
попробовать такой трюк:
1. Сделать резервную копию, которую будете уносить (mysqlhotcopy)
2. Очистить раздел (TRUNCATE PARTITION)
При этом раздел у Вас останется, просто он будет пустым. Когда нужно бу-
дет восстановить раздел — нужно будет:
1. Заблокировать табличку (LOCK TABLES .. WRITE);
2. Сбросить кэши на диск (FLUSH TABLES ..);
3. Перезаписать файлы восстанавливаемого раздела;
4. Разблокировать табличку (UNLOCK TABLES);
Этапы 1 и 4 должны выполняться отдельным соединением, которое должно
держать блокировку в процессе работы (т.е. выполнить 1 и закрыть клиент
нельзя).
Ну и потренируйтесь на небоевых данных сначала, конечно.
Неактивен
Здравствуйте.
Есть еще такой вопрос по данной теме.
Если создается таблица (как в предыдущем примере):
CREATE TABLE t4 (
fname VARCHAR(50) NOT NULL,
lname VARCHAR(50) NOT NULL,
region_code TINYINT UNSIGNED NOT NULL,
dob DATE NOT NULL
)
PARTITION BY KEY(region_code)
PARTITIONS 8;
то что обозначает директива "PARTITIONS 8"?
Если у нас будет 5000 разных "region_code" она все равно создаст 8 частей таблицы?
И где какие данные будут находиться?
И как понять такой код?
PARTITION BY KEY ()
(
PARTITION partition1 ENGINE = INNODB,
PARTITION partition2 ENGINE = INNODB
);
Заранее спасибо.
Отредактированно Vitas (02.01.2014 01:35:38)
Неактивен
PARTITIONS 8 означает, что таблица будет разбита на 8 разделов. Данные будут разнесены по значению ключа region_code по принципу "на первый - восьмой рассчитась!".
Во втором случае будет два раздела, у обоих указан механизм хранения Innodb. MySQL хранит разделы как отдельные таблицы, поэтому в принципе они могут иметь и разный механизм хранения (в MySQL 5.5 если указать у второго раздела Engine=MyISAM, будет ошибка "ERROR 1497 (HY000): The mix of handlers in the partitions is not allowed in this version of MySQL" )
Неактивен
rgbeast написал:
PARTITIONS 8 означает, что таблица будет разбита на 8 разделов. Данные будут разнесены по значению ключа region_code по принципу "на первый - восьмой рассчитась!".
Тогда вопрос как выбрать оптимальное значение этого параметра? На чем основываться при выборе?
rgbeast написал:
Во втором случае будет два раздела, у обоих указан механизм хранения Innodb. MySQL хранит разделы как отдельные таблицы, поэтому в принципе они могут иметь и разный механизм хранения (в MySQL 5.5 если указать у второго раздела Engine=MyISAM, будет ошибка "ERROR 1497 (HY000): The mix of handlers in the partitions is not allowed in this version of MySQL" )
Данный синтаксис идентичен комманде "PARTITIONS 2"?
Или это реально 2 таблицы, а не 2 части одной таблицы?
Неактивен
Vitas написал:
Тогда вопрос как выбрать оптимальное значение этого параметра? На чем основываться при выборе?
основываться на тестах производительности
Vitas написал:
Данный синтаксис идентичен комманде "PARTITIONS 2"?
Или это реально 2 таблицы, а не 2 части одной таблицы?
эквивалентно PARTITIONS 2. Физически (на уровне хранилища) разделы в любом случае хранятся как если бы это были отдельные таблицы, но обращение к ним как к одной таблице.
Неактивен