cергей Голубчик, monty program ab

23
Оптимизатор запросов в MariaDB 10.0 — теперь и без индексов! Сергей Голубчик MariaDB

Upload: ontico

Post on 03-Aug-2015

539 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Cергей Голубчик, Monty Program AB

Оптимизатор запросов в MariaDB 10.0 — теперь и без индексов!

Сергей Голубчик MariaDB

Page 2: Cергей Голубчик, Monty Program AB

Об этом докладе

● Engine Independent Statistics

● Что это такое

● Зачем это нужно

● Как считается

● Где хранится

● Примеры, примеры, примеры

Page 3: Cергей Голубчик, Monty Program AB

Статистика данных: как это было

● Оптимизатор спрашивает движок:

● «сколько примерно строк в таблице?»

● «сколько стоит просканировать всю таблицу?»

● «сколько стоит прочитать столько-то строк из такого-то индекса?»

● «сколько раз в среднем каждое значение встречается в таком-то

индексе?»

● «сколько значений в таком-то индексе попадает в диапазон от… и

до…?»

Page 4: Cергей Голубчик, Monty Program AB

Пример: нестабильность

● DBT-3: сложные аналитические запросы

● Q7: Volume Shipping Query

– 6 InnoDB таблиц

– 7 разных планов

– 12 минут, 25 минут, часы (таймаут)

● Q8: National Market Share Query

– 8 InnoDB таблиц

– 4 разных плана

– от 7 минут до 1.2 часа

Page 5: Cергей Голубчик, Monty Program AB

Пример: неправда 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 |

+-------------+

Page 6: Cергей Голубчик, Monty Program AB

Независимая статистика

● стабильная

● точная

● одинаковая для всех движков

Page 7: Cергей Голубчик, Monty Program AB

Как это сделано

● новые таблицы в mysql

● конфигурационные переменные

● расширенная команда ANALYZE TABLE

Page 8: Cергей Голубчик, Monty Program AB

Таблицы

● mysql.table_stats

● mysql.index_stats

● mysql.column_stats

Page 9: Cергей Голубчик, Monty Program AB

Переменные

● @@use_stat_tables

● never

● complementary

● preferably

● @@optimizer_use_condition_selectivity

● 1 … 5

Page 10: Cергей Голубчик, Monty Program AB

Команда ANALYZE TABLE

● ANALYZE TABLE table_name

● ANALYZE TABLE table_name PERSISTENT FOR ALL

● ANALYZE TABLE table_name PERSISTENT FOR

COLUMNS (column1, column2, ...)

INDEXES (index1, index2, ...)

Page 11: Cергей Голубчик, Monty Program AB

Что считается

● по таблицам

● количество строк

● по индексам

● обратная мощность

Page 12: Cергей Голубчик, Monty Program AB

Что считается

● по столбцам

● минимальное и максимальное значения

● процент NULL-ов

● средняя длина значения

● обратная мощность

● распределение значений (гистограмма)

Page 13: Cергей Голубчик, Monty Program AB

Пример

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)

Page 14: Cергей Голубчик, Monty Program AB

Пример

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)

Page 15: Cергей Голубчик, Monty Program AB

Пример 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 |

| 1 | departments | ALL | NULL | 9 | 77.78 | Using where; Using join

Page 16: Cергей Голубчик, Monty Program AB

Неравномерное распределение

● Таблица скачиваний какого-то продукта N

● Пусть, пользователи могут регистрироваться

– и, где-то 1% на самом деле это делает

1,000,000 rows

среднее количество строк на значение: 500,000 10 000

990 000

Registered

YES

NO

… WHERE Registered = 'YES' …

Page 17: Cергей Голубчик, Monty Program AB

Гистограммы

● histogram_size=20 или любое число больше нуля

● optimizer_use_condition_selectivity=4 или 5

● histogram_type=single_prec_hb или double_prec_hb

Page 18: Cергей Голубчик, Monty Program AB

Гистограммы равной высоты

Page 19: Cергей Голубчик, Monty Program AB

Пример 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)

Page 20: Cергей Голубчик, Monty Program AB

Пример 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)

Page 21: Cергей Голубчик, Monty Program AB

Планы

● Другие типы гистограмм (например, равной ширины)

● Гистограммы для индексов (из нескольких столбцов!)

● Учет корреляций между столбцами

Page 22: Cергей Голубчик, Monty Program AB

Вопросы?

Page 23: Cергей Голубчик, Monty Program AB

Спасибо за внимание!