2. Об этом докладе
●
Engine Independent Statistics
●
Что это такое
●
Зачем это нужно
●
Как считается
●
Где хранится
●
Примеры, примеры, примеры
3. Статистика данных: как это было
●
Оптимизатор спрашивает движок:
●
«сколько примерно строк в таблице?»
●
«сколько стоит просканировать всю таблицу?»
●
«сколько стоит прочитать столько-то строк из такого-то индекса?»
●
●
«сколько раз в среднем каждое значение встречается в таком-то
индексе?»
«сколько значений в таком-то индексе попадает в диапазон от… и
до…?»
4. Пример: нестабильность
●
DBT-3: сложные аналитические запросы
●
Q7: Volume Shipping Query
●
6 InnoDB таблиц
– 7 разных планов
– 12 минут, 25 минут, часы (таймаут)
Q8: National Market Share Query
–
–
–
–
8 InnoDB таблиц
4 разных плана
от 7 минут до 1.2 часа
5. Пример: неправда
MariaDB [test]> CREATE TABLE t1 (a INT, b INT, c INT, KEY(a,b)) ENGINE=MyISAM;
MariaDB [test]> INSERT t1 VALUES (RAND()*1e5,RAND()*1e5,RAND()*1e5);
... 400 000 rows ...
MariaDB [test]> SELECT COUNT(DISTINCT a) AS cardinality FROM t1;
+-------------+
| cardinality |
+-------------+
|
97794 |
+-------------+
MariaDB [test]> SELECT cardinality FROM information_schema.statistics
--> WHERE table_name='t1' AND column_name='a';
+-------------+
| cardinality |
+-------------+
|
98304 |
+-------------+
MariaDB [test]> ALTER TABLE t1 ENGINE=InnoDB;
MariaDB [test]> SELECT cardinality FROM information_schema.statistics
--> WHERE table_name='t1' AND column_name='a';
+-------------+
| cardinality |
+-------------+
|
196914 |
+-------------+
12. Что считается
●
по столбцам
●
минимальное и максимальное значения
●
процент NULL-ов
●
средняя длина значения
●
обратная мощность
●
распределение значений (гистограмма)
13. Пример
CREATE TABLE t1 (a INT, b INT);
INSERT t1 SELECT RAND()*1e5, RAND()*1e5;
. . . . . . . . . .
-- 512 тысяч строк
CREATE TABLE t2 (c INT, d INT, KEY(c), KEY(d));
INSERT t2 SELECT FLOOR(RAND()*1e5/2)*2, FLOOR(RAND()*1e5/3)*3 FROM t1;
CREATE TABLE t3 (e INT, f INT, KEY(f));
INSERT t3 SELECT * FROM t2;
ANALYZE TABLE t3;
SET OPTIMIZER_USE_CONDITION_SELECTIVITY=1;
SELECT * FROM t1, t2, t3 WHERE t3.f=t1.a AND t2.c=t1.a AND t3.e<5;
--> 1075 rows in set (1 min 19.25 sec)
SET OPTIMIZER_USE_CONDITION_SELECTIVITY=3;
SELECT * FROM t1, t2, t3 WHERE t3.f=t1.a AND t2.c=t1.a AND t3.e<5;
--> 1075 rows in set (13.17 sec)
14. Пример
MariaDB [test]> . employees.sql
MariaDB [employees]> ANALYZE TABLE departments, dept_emp, dept_manager,
-> employees, salaries, titles;
MariaDB [employees]> SET OPTIMIZER_USE_CONDITION_SELECTIVITY=1;
Query OK, 0 rows affected (0.01 sec)
MariaDB [employees]> SELECT * FROM departments JOIN dept_emp USING (dept_no)
-> JOIN employees USING (emp_no) JOIN titles USING (emp_no) WHERE title='Manager';
24 rows in set (15.13 sec)
MariaDB [employees]> SET OPTIMIZER_USE_CONDITION_SELECTIVITY=3;
Query OK, 0 rows affected (0.01 sec)
MariaDB [employees]> SELECT * FROM departments JOIN dept_emp USING (dept_no)
-> JOIN employees USING (emp_no) JOIN titles USING (emp_no) WHERE title='Manager';
24 rows in set (0.53 sec)
15. Пример
MariaDB [employees]> EXPLAIN EXTENDED SELECT * FROM departments JOIN dept_emp USING
(dept_no)
-> JOIN employees USING (emp_no) JOIN titles USING (emp_no) WHERE title='Manager';
+------+-------------+--------+---------+-------+----------+-----------------------+
| id
| table
| type
| key
| rows | filtered | Extra
|
+------+-------------+--------+---------+-------+----------+-----------------------+
|
1 | departments | ALL
| NULL
|
9 |
100.00 |
|
|
1 | dept_emp
| ref
| dept_no | 36844 |
100.00 |
|
|
1 | employees
| eq_ref | PRIMARY |
1 |
100.00 |
|
|
1 | titles
| ref
| PRIMARY |
1 |
100.00 | Using index condition |
+------+-------------+--------+---------+-------+----------+-----------------------+
MariaDB [employees]> SET OPTIMIZER_USE_CONDITION_SELECTIVITY=3;
MariaDB [employees]> EXPLAIN EXTENDED SELECT * FROM departments JOIN dept_emp USING
(dept_no)
-> JOIN employees USING (emp_no) JOIN titles USING (emp_no) WHERE title='Manager';
+------+-------------+--------+---------+--------+----------+-----------------------------| id
| table
| type
| key
| rows
| filtered | Extra
+------+-------------+--------+---------+--------+----------+-----------------------------|
1 | titles
| ALL
| NULL
| 443308 |
14.29 | Using where
|
1 | employees
| eq_ref | PRIMARY |
1 |
100.00 |
|
1 | dept_emp
| ref
| PRIMARY |
1 |
100.00 |
16. Неравномерное распределение
●
Таблица скачиваний какого-то продукта N
●
Пусть, пользователи могут регистрироваться
–
и, где-то 1% на самом деле это делает
… WHERE Registered = 'YES' …
990 000
YES
1,000,000 rows
среднее количество строк на значение: 500,000
NO
10 000
Registered
19. Пример
MariaDB [employees]> SET OPTIMIZER_USE_CONDITION_SELECTIVITY=3;
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> SELECT * FROM employees JOIN salaries
-> USING (emp_no) JOIN titles USING (emp_no) WHERE salary > 100000;
166014 rows in set (18.79 sec)
MariaDB [employees]> SET OPTIMIZER_USE_CONDITION_SELECTIVITY=4;
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> SELECT * FROM employees JOIN salaries
-> USING (emp_no) JOIN titles USING (emp_no) WHERE salary > 100000;
166014 rows in set (6.64 sec)
20. Пример
MariaDB [employees]> EXPLAIN EXTENDED SELECT * FROM employees JOIN salaries
-> USING (emp_no) JOIN titles USING (emp_no) WHERE salary > 100000;
+------+-----------+--------+---------+--------+----------+-------------+
| id
| table
| type
| key
| rows
| filtered | Extra
|
+------+-----------+--------+---------+--------+----------+-------------+
|
1 | titles
| ALL
| NULL
| 443308 |
100.00 |
|
|
1 | employees | eq_ref | PRIMARY |
1 |
100.00 |
|
|
1 | salaries | ref
| PRIMARY |
9 |
48.68 | Using where |
+------+-----------+--------+---------+--------+----------+-------------+
3 rows in set, 1 warning (0.00 sec)
MariaDB [employees]> SET OPTIMIZER_USE_CONDITION_SELECTIVITY=4;
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> EXPLAIN EXTENDED SELECT * FROM employees JOIN salaries
-> USING (emp_no) JOIN titles USING (emp_no) WHERE salary > 100000;
+------+-----------+--------+---------+---------+----------+-------------+
| id
| table
| type
| key
| rows
| filtered | Extra
|
+------+-----------+--------+---------+---------+----------+-------------+
|
1 | salaries | ALL
| NULL
| 2844047 |
4.76 | Using where |
|
1 | employees | eq_ref | PRIMARY |
1 |
100.00 |
|
|
1 | titles
| ref
| PRIMARY |
1 |
100.00 |
|
+------+-----------+--------+---------+---------+----------+-------------+
3 rows in set, 1 warning (0.01 sec)
21. Планы
●
Другие типы гистограмм (например, равной ширины)
●
Гистограммы для индексов (из нескольких столбцов!)
●
Учет корреляций между столбцами