Spec-Zone .ru
спецификации, руководства, описания, API
|
MySQL 5.6 поддерживает явный выбор разделов и подразделов, которые, выполняя оператор, должны быть проверены на
строки, соответствующие данный WHERE
условие. Выбор раздела подобен сокращению
раздела, в тот, единственные определенные разделы проверяются на соответствия, но отличается по двум ключевым
отношениям:
Разделы, которые будут проверены, определяются выпускающим оператора, в отличие от сокращения раздела, которое является автоматическим.
Принимая во внимание, что сокращение раздела применяется только к запросам, явный выбор разделов поддерживается для обоих запросов и многих операторов DML.
SQL-операторы, поддерживающие явный выбор раздела, перечисляются здесь:
Остаток от этого раздела обсуждает явный выбор раздела, поскольку это применяется обычно к операторам, только перечисленным, и обеспечивает некоторые примеры.
Явный выбор раздела реализуется, используя a PARTITION
опция. Для всех
поддерживаемых операторов эта опция использует синтаксис, показанный здесь:
PARTITION (partition_names
)partition_names
:partition_name
, ...
Эта опция всегда следует за именем таблицы, которой принадлежат раздел или разделы. partition_names
список разделенных запятой значений разделов или
подразделов, которые будут использоваться. Каждое имя в этом списке должно быть именем существующего раздела или
подраздела указанной таблицы; если какой-либо из разделов или подразделов не находится, сбои оператора с ошибкой
(раздел'partition_name
'не существует).
Разделы и подразделы, названные в partition_names
может быть
перечислен в любом порядке, и может наложиться.
Когда PARTITION
опция используется, только разделы и перечисленные подразделы
проверяются на то, что они соответствовали строки. Эта опция может использоваться в a SELECT
оператор, чтобы определить, какие строки принадлежат данному разделу.
Считайте разделенную таблицу названной employees
, создаваемое и заполненное
использование операторов, показанных здесь:
SET @@SQL_MODE = '';CREATE TABLE employees ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, fname VARCHAR(25) NOT NULL, lname VARCHAR(25) NOT NULL, store_id INT NOT NULL, department_id INT NOT NULL) PARTITION BY RANGE(id) ( PARTITION p0 VALUES LESS THAN (5), PARTITION p1 VALUES LESS THAN (10), PARTITION p2 VALUES LESS THAN (15), PARTITION p3 VALUES LESS THAN MAXVALUE);INSERT INTO employees VALUES ('', 'Bob', 'Taylor', 3, 2), ('', 'Frank', 'Williams', 1, 2), ('', 'Ellen', 'Johnson', 3, 4), ('', 'Jim', 'Smith', 2, 4), ('', 'Mary', 'Jones', 1, 1), ('', 'Linda', 'Black', 2, 3), ('', 'Ed', 'Jones', 2, 1), ('', 'June', 'Wilson', 3, 1), ('', 'Andy', 'Smith', 1, 3), ('', 'Lou', 'Waters', 2, 4), ('', 'Jill', 'Stone', 1, 4), ('', 'Roger', 'White', 3, 2), ('', 'Howard', 'Andrews', 1, 2), ('', 'Fred', 'Goldberg', 3, 3), ('', 'Barbara', 'Brown', 2, 3), ('', 'Alice', 'Rogers', 2, 2), ('', 'Mark', 'Morgan', 3, 3), ('', 'Karen', 'Cole', 3, 2);
Можно видеть, какие строки сохранены в разделе p1
как это:
mysql> SELECT * FROM employees PARTITION (p1);
+----+-------+--------+----------+---------------+| id | fname | lname | store_id | department_id |+----+-------+--------+----------+---------------+| 5 | Mary | Jones | 1 | 1 || 6 | Linda | Black | 2 | 3 || 7 | Ed | Jones | 2 | 1 || 8 | June | Wilson | 3 | 1 || 9 | Andy | Smith | 1 | 3 |+----+-------+--------+----------+---------------+5 rows in set (0.00 sec)
Результатом является то же самое как получено запросом SELECT * FROM employees WHERE id
BETWEEN 5 AND 9
.
Чтобы получить строки из многократных разделов, предоставьте их имена как разграниченный запятой список.
Например, SELECT * FROM employees PARTITION (p1, p2)
возвраты все строки от
разделов p1
и p2
в то время как, исключая строки от
остающихся разделов.
Любой допустимый запрос против разделенной таблицы может быть переписан с a PARTITION
опция, чтобы ограничить результат один или более требуемые разделы. Можно
использовать WHERE
условия, ORDER BY
и LIMIT
опции, и так далее. Можно также использовать агрегатные функции с HAVING
и GROUP BY
опции. Каждый из следующих
запросов приводит к допустимому результату когда работающийся employees
таблица как
ранее определено:
mysql>SELECT * FROM employees PARTITION (p0, p2)
->WHERE lname LIKE 'S%';
+----+-------+-------+----------+---------------+| id | fname | lname | store_id | department_id |+----+-------+-------+----------+---------------+| 4 | Jim | Smith | 2 | 4 || 11 | Jill | Stone | 1 | 4 |+----+-------+-------+----------+---------------+2 rows in set (0.00 sec)mysql>SELECT id, CONCAT(fname, ' ', lname) AS name
->FROM employees PARTITION (p0) ORDER BY lname;
+----+----------------+| id | name |+----+----------------+| 3 | Ellen Johnson || 4 | Jim Smith || 1 | Bob Taylor || 2 | Frank Williams |+----+----------------+4 rows in set (0.06 sec)mysql>SELECT store_id, COUNT(department_id) AS c
->FROM employees PARTITION (p1,p2,p3)
->GROUP BY store_id HAVING c > 4;
+---+----------+| c | store_id |+---+----------+| 5 | 2 || 5 | 3 |+---+----------+2 rows in set (0.00 sec)
Операторы используя выбор раздела могут использоваться с таблицами, используя любой из типов разделения,
поддерживаемых в MySQL 5.6. Когда таблица составляется, используя [LINEAR] HASH
или
[LINEAR] KEY
разделение и имена разделов не определяются, MySQL автоматически
называет разделы p0
, p1
, p2
, ..., p
, где N-1
N
число
разделов. Для подразделов, не явно названных, MySQL присваивается автоматически к подразделам в каждом разделе
p
имена X
p
, X
sp0p
,
X
sp1p
, ..., X
sp2p
, где X
spM-1
M
число подразделов. Выполняясь против этой таблицы a SELECT
(или другой SQL-оператор, для которого позволяется явный выбор
раздела), можно использовать эти сгенерированные имена в a PARTITION
опция, как
показано здесь:
mysql>CREATE TABLE employees_sub (
->id INT NOT NULL AUTO_INCREMENT,
->fname VARCHAR(25) NOT NULL,
->lname VARCHAR(25) NOT NULL,
->store_id INT NOT NULL,
->department_id INT NOT NULL,
->PRIMARY KEY pk (id, lname)
->)
->PARTITION BY RANGE(id)
->SUBPARTITION BY KEY (lname)
->SUBPARTITIONS 2 (
->PARTITION p0 VALUES LESS THAN (5),
->PARTITION p1 VALUES LESS THAN (10),
->PARTITION p2 VALUES LESS THAN (15),
->PARTITION p3 VALUES LESS THAN MAXVALUE
->);
Query OK, 0 rows affected (1.14 sec)mysql>INSERT INTO employees_sub
# re-use data in employees table ->SELECT * FROM employees;
Query OK, 18 rows affected (0.09 sec)Records: 18 Duplicates: 0 Warnings: 0mysql>SELECT id, CONCAT(fname, ' ', lname) AS name
->FROM employees_sub PARTITION (p2sp1);
+----+---------------+| id | name |+----+---------------+| 10 | Lou Waters || 14 | Fred Goldberg |+----+---------------+2 rows in set (0.00 sec)
Можно также использовать a PARTITION
опция в SELECT
часть INSERT
... SELECT
оператор, как показано здесь:
mysql>CREATE TABLE employees_copy LIKE employees;
Query OK, 0 rows affected (0.28 sec)mysql>INSERT INTO employees_copy
->SELECT * FROM employees PARTITION (p2);
Query OK, 5 rows affected (0.04 sec)Records: 5 Duplicates: 0 Warnings: 0mysql>SELECT * FROM employees_copy;
+----+--------+----------+----------+---------------+| id | fname | lname | store_id | department_id |+----+--------+----------+----------+---------------+| 10 | Lou | Waters | 2 | 4 || 11 | Jill | Stone | 1 | 4 || 12 | Roger | White | 3 | 2 || 13 | Howard | Andrews | 1 | 2 || 14 | Fred | Goldberg | 3 | 3 |+----+--------+----------+----------+---------------+5 rows in set (0.00 sec)
Выбор раздела может также использоваться с соединениями. Предположите, что мы создаем и заполняем две таблицы, используя операторы, показанные здесь:
CREATE TABLE stores ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, city VARCHAR(30) NOT NULL) PARTITION BY HASH(id) PARTITIONS 2; INSERT INTO stores VALUES ('', 'Nambucca'), ('', 'Uranga'), ('', 'Bellingen'), ('', 'Grafton'); CREATE TABLE departments ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(30) NOT NULL) PARTITION BY KEY(id) PARTITIONS 2; INSERT INTO departments VALUES ('', 'Sales'), ('', 'Customer Service'), ('', 'Delivery'), ('', 'Accounting');
Можно явно выбрать разделы (или подразделы, или обоих) от любых из таблиц в соединении. (Отметьте что PARTITION
опция, используемая, чтобы выбрать разделы из данной таблицы сразу, следует
за именем таблицы, перед всеми другими опциями, включая любой табличный псевдоним.) Например, следующий запрос
завоевывает репутацию, ID сотрудника, отдел, и город всех сотрудников, которые работают в продажах или отделе
Поставки (раздел p1
из departments
таблица) в
хранилищах в любом из городов Nambucca и Bellingen (раздел p0
из stores
таблица):
mysql>SELECT
->e.id AS 'Employee ID', CONCAT(e.fname, ' ', e.lname) AS Name,
->s.city AS City, d.name AS department
->FROM employees AS e
->JOIN stores PARTITION (p1) AS s ON e.store_id=s.id
->JOIN departments PARTITION (p0) AS d ON e.department_id=d.id
->ORDER BY e.lname;
+-------------+---------------+-----------+------------+| Employee ID | Name | City | department |+-------------+---------------+-----------+------------+| 14 | Fred Goldberg | Bellingen | Delivery || 5 | Mary Jones | Nambucca | Sales || 17 | Mark Morgan | Bellingen | Delivery || 9 | Andy Smith | Nambucca | Delivery || 8 | June Wilson | Bellingen | Sales |+-------------+---------------+-----------+------------+5 rows in set (0.00 sec)
Для получения общей информации об участвует в MySQL, см. Раздел 13.2.9.2,"JOIN
Синтаксис".
Когда PARTITION
опция используется с DELETE
операторы, только те разделы (и подразделы, если кто-либо) перечисленный с
опцией проверяются на строки, которые будут удалены. Любые другие разделы игнорируются, как показано здесь:
mysql>SELECT * FROM employees WHERE fname LIKE 'j%';
+----+-------+--------+----------+---------------+| id | fname | lname | store_id | department_id |+----+-------+--------+----------+---------------+| 4 | Jim | Smith | 2 | 4 || 8 | June | Wilson | 3 | 1 || 11 | Jill | Stone | 1 | 4 |+----+-------+--------+----------+---------------+3 rows in set (0.00 sec)mysql>DELETE FROM employees PARTITION (p0, p1)
->WHERE fname LIKE 'j%';
Query OK, 2 rows affected (0.09 sec)mysql>SELECT * FROM employees WHERE fname LIKE 'j%';
+----+-------+-------+----------+---------------+| id | fname | lname | store_id | department_id |+----+-------+-------+----------+---------------+| 11 | Jill | Stone | 1 | 4 |+----+-------+-------+----------+---------------+1 row in set (0.00 sec)
Только эти две строки в разделах p0
и p1
соответствие
WHERE
условие было удалено. Поскольку можно видеть от результата когда SELECT
выполняется во второй раз, там остается строкой в таблице,
соответствующей WHERE
условие, но находящийся в различном разделе (p2
).
UPDATE
операторы используя явный выбор раздела ведут себя таким же образом; только строки в разделах, на которые
ссылаются PARTITION
опцию рассматривают, определяя строки, которые будут обновлены,
как может быть замечен, выполняя следующие операторы:
mysql>UPDATE employees PARTITION (p0)
->SET store_id = 2 WHERE fname = 'Jill';
Query OK, 0 rows affected (0.00 sec)Rows matched: 0 Changed: 0 Warnings: 0mysql>SELECT * FROM employees WHERE fname = 'Jill';
+----+-------+-------+----------+---------------+| id | fname | lname | store_id | department_id |+----+-------+-------+----------+---------------+| 11 | Jill | Stone | 1 | 4 |+----+-------+-------+----------+---------------+1 row in set (0.00 sec)mysql>UPDATE employees PARTITION (p2)
->SET store_id = 2 WHERE fname = 'Jill';
Query OK, 1 row affected (0.09 sec)Rows matched: 1 Changed: 1 Warnings: 0mysql>SELECT * FROM employees WHERE fname = 'Jill';
+----+-------+-------+----------+---------------+| id | fname | lname | store_id | department_id |+----+-------+-------+----------+---------------+| 11 | Jill | Stone | 2 | 4 |+----+-------+-------+----------+---------------+1 row in set (0.00 sec)
Таким же образом, когда PARTITION
используется с DELETE
, только строки в разделе или разделах, названных в списке раздела,
проверяются на удаление.
Для операторов, которые вставляют строки, поведение отличается по тому отказу найти, что подходящий раздел
заставляет оператор перестать работать. Это - истина для обоих INSERT
и REPLACE
операторы, как показано здесь:
mysql>INSERT INTO employees PARTITION (p2) VALUES (20, 'Jan', 'Jones', 1, 3);
ERROR 1729 (HY000): Found a row not matching the given partition setmysql>INSERT INTO employees PARTITION (p3) VALUES (20, 'Jan', 'Jones', 1, 3);
Query OK, 1 row affected (0.07 sec)mysql> REPLACE INTO employees PARTITION (p0) VALUES (20, 'Jan', 'Jones', 3, 2);ERROR 1729 (HY000): Found a row not matching the given partition setmysql> REPLACE INTO employees PARTITION (p3) VALUES (20, 'Jan', 'Jones', 3, 2);Query OK, 2 rows affected (0.09 sec)
Для операторов, которые пишут многократные строки в разделенную таблицу, которая использует InnoDB
механизм хранения: Если любая строка в списке после VALUES
не может быть записан одному из разделов, определенных в partition_names
список, все сбои оператора и никакие строки
пишутся. Для этого показывают INSERT
операторы в следующем примере, снова используя employees
таблица, составленная ранее:
mysql>ALTER TABLE employees
->REORGANIZE PARTITION p3 INTO (
->PARTITION p3 VALUES LESS THAN (20),
->PARTITION p4 VALUES LESS THAN (25),
->PARTITION p5 VALUES LESS THAN MAXVALUE
->);
Query OK, 6 rows affected (2.09 sec)Records: 6 Duplicates: 0 Warnings: 0mysql>SHOW CREATE TABLE employees\G
*************************** 1. row *************************** Table: employeesCreate Table: CREATE TABLE `employees` ( `id` int(11) NOT NULL AUTO_INCREMENT, `fname` varchar(25) NOT NULL, `lname` varchar(25) NOT NULL, `store_id` int(11) NOT NULL, `department_id` int(11) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=latin1/*!50100 PARTITION BY RANGE (id)(PARTITION p0 VALUES LESS THAN (5) ENGINE = InnoDB, PARTITION p1 VALUES LESS THAN (10) ENGINE = InnoDB, PARTITION p2 VALUES LESS THAN (15) ENGINE = InnoDB, PARTITION p3 VALUES LESS THAN (20) ENGINE = InnoDB, PARTITION p4 VALUES LESS THAN (25) ENGINE = InnoDB, PARTITION p5 VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */1 row in set (0.00 sec)mysql>INSERT INTO employees PARTITION (p3, p4) VALUES
->(24, 'Tim', 'Greene', 3, 1), (26, 'Linda', 'Mills', 2, 1);
ERROR 1729 (HY000): Found a row not matching the given partition setmysql>INSERT INTO employees PARTITION (p3, p4. p5) VALUES
->(24, 'Tim', 'Greene', 3, 1), (26, 'Linda', 'Mills', 2, 1);
Query OK, 2 rows affected (0.06 sec)Records: 2 Duplicates: 0 Warnings: 0
Предыдущей является истина для обоих INSERT
операторы и REPLACE
операторы, которые пишут многократные строки.
В MySQL 5.6.10 и позже, выбор раздела отключается для таблиц, использующих механизм хранения, который
предоставляет автоматическое разделение, такой как NDB
. (Ошибка #14827952)