Оптимизация производительности 
aka 
«тюнинг» MySQL 
IBEC brainstorm
Не будем говорить о… 
 Железе 
 Академическом составляющим MySQL или то, что можно легко найти 
почитать в интернете (triggers, stored procedures, views…). 
 Движках (Data engines) 
 Партиционировании (Partitioning) 
 Шардинге (Sharding)
О чем будем говорить? 
 О чем должен знать каждый разработчик? 
 Что такое индексы и как их правильно использовать 
 Базовые настройки MySQL my.cnf (my.ini) 
 Системные переменные (System Variables) и как ими манипулировать 
 Мониторинг сервера БД на узкие места 
 Оптимизация запросов к БД 
 Знаем ли мы фичи наших IDE? HeidiSQL, Navicat. 
 Репликации 
 О чем нибудь да поговорим. PHP, byte code, gzip.
Индексы 
 Почему сначала об индексах? 
 Что это такое вообще? 
Обычно работаем с B tree индексами, о них и поговорим
Принцип работы B tree 
https://bubbl.us/ 
 Отсортированы по порядку 
 Легко делать поиск 
 Левый крайний нод – min value 
 Правый крайний нод – max value 
 Левный нод не будет иметь значение больше или 
равно чем родитель (X). 
 Правый нод - минимальное значение - это Х. 
Будет больше или равно X 
* Ключи хранятся в индекском файле упорядоченном по принципу 
Сбаларнсированного бинарного дерева
Алгоритм поиска 
Linear (by sequence) 
Sorted 4 binary search
Поиск по индексу 
Ищем id-354 
48=354? false 
48<354? true 
354? false
Поиск по индксу 
Ищем id-354 
354? true
Пример B+ дерева, связывающего ключи 1-7 с данными d1-d7. 
Связи (выделены красным) позволяют быстро обходить дерево в порядке возрастания ключей. 
Каждый листовой узел содержит указатель на следующий для ускорения обхода.
Забегаем вперед. EXPLAIN 
Как посмотреть какой индекс используется? EXPLAIN <select query> 
3 интересных поля: 
 Используемый ключь 
 Количество проверяемых столбцов. Нужно стараться минимизировать. 
 Экстра. То что делает БД в процессе исполнения запроса. 
Хорошо: Using index, Плохо: Using filesort, create tmp tbl, create tmp tbl on disk
Практика, самая первая + 
EXPLAIN 
 SELECT * FROM t WHERE t.a*=x SELECT id FROM mytest where id4=80 
Query time 0.073s 
Query time 0.002s
Далее… 
 SELECT * FROM t WHERE t.a=x LIMIT 10 
 SELECT * FROM t WHERE t.a=x ORDER BY t.b LIMIT 10 
Query time 0.060s
Еще… 
 MySQL не знает как использовать 2 разных индекса одной таблицы. 
 Решение? Композиционный ключь. 
ALTER TABLE mytest ADD INDEX ixId23(id2,id3); 
 Индекс(Фамилия, имя) – составной ключь. Нельзя искать сначала И, потом Ф. Ф потом И. 
 “Using filesort” – плохо. sort_buffer_size –2M (default ) 
Тада! 
 Обратная сортировка DESC не меняет сложность запроса 
 Индекс (А,B) типо= индекс (A). А можно удалить
Еще чуть об индексах 
Индекс(A,B,C) 
позволяет: 
WHERE A=10 AND B>10; 
WHERE A=10 AND B=11 AND C=12; 
WHERE A=10 AND B=11 ORDER BY C; 
не позволяет: 
WHERE B=10; 
WHERE A=10 AND B>10 AND C>10 
SELECT... WHERE func(idx)=20 - не будет использовать 
SELECT... WHERE idx = func(20) - может использовать индекс
Ах да… 
Существует граничное условие, начиная с которого использование индекса начинает проигрывать 
последовательному сканированию всей таблицы. 
Происходит это тогда, когда количество выбираемых с помощью индекса записей больше 
определенного процента (~30% нужно найти в справочнике точную цифру) 
от общего количества записей в таблице. 
Не нужно индексировать все подряд. MySQL все равно выберет какой-то один, но зато вы проиграете 
на insert, update.
По-сложнее. Пагинатор 
 Все плохо 
 SELECT * FROM t WHERE t.a=x LIMIT 1000,10 
Handler_read_next = 1009 
 Может хостер не виноват? 
 Google, Яндекс и другие десятки поисковиков.
Как решить? EXPLAIN врет! 
 SELECT id FROM mytest WHERE id>1000 ORDER BY id LIMIT 10 
 Что говорит Handler_read_next? - 9!
Чуть сложнее 
 3 условия WHERE и сортировка 
SELECT * FROM t WHERE t.a=x AND t.b=y AND t.c>z ORDER BY t.d 
Какой индекс будет оптимальным, Abc, bcd, abd? 
 Abc, abd. Индексы не любят когда над ними производятся функкции и выражения 
 A и B можно менять местами, математические действия всегда в конце.
Ладно. Highload 
 Умный человек сказал «Преждевременная оптимизация – корень всех зол» 
 Есть проект 
 Нагрузка выросла. Клиенты ругаются на производительность. 
 Что можем сделать на уровне MySQL?
Лог медленных запросов 
 Log_slow_queries; long_query_time=1 
долгие запросы 
 Log_queries_not_using_indexes 
запросы не использующие индексы 
 Shell> Mysqldumpslow 
 Всевозможные патчи mysqlsla, mysql_parse_slow etc 
http://www.mysqlperformanceblog.com
Тюнинг My.cnf (my.ini) 
 Настройки по умолчанию – плохо 
 Основа: Использование памяти лучше чем использование диска. 
 Что важнее? Настройка потребления памяти 
 Не пытайтесь тюнить все, для большинства приложении нужно изменить всего 
несколько параметров
Хороший тон тюнинга. Правила 
 Никогда не делать изменения сначала на продакшне 
 Иметь хорошие инструменты для бенчмарка 
 Одно изменение за одно время 
 В голове перекиньте возможные изменения 
 Пробуйте каждое изменение отдельно 
 Пробуйте в комбинации 2, потом 3 изменении итд 
 Мониторить результат 
Время за один запрос, Среднее время запроса 
 Задокументируйте
Важные параметры 
 key_buffer_size – кэш индексов MyISAM 
- Используется для временных таблиц даже если все Innodb 
- 30% если только MyISAM, 32M если наоборот. 
- Временные таблицы в MyISAM 
- Данные MyISAM не кеширует, они в кэше ОС 
 table_cache – число открытых таблиц 
- См рост opened_tables 
 query_cache_size – Внутренний кэш MySQL 
- Если запросы не менялись, результат берется из кэша. 
- Может быть полезен если нет умного кэширования. 
- 32М обычно достаточно.
Как работает key cache 
 На чтение. Смотрит в буфер, если есть возвращает, если нет считывает MYI файл 
 На запись. Пробивает индекс, убирает все ключи. 
Наблюдайте за переменными состояния Key_reads и Key_read_requests, 
отношение Key_reads/Key_read_requests должно быть как можно меньше (< 0,01). 
Если это отношение велико, то размер буфера стоит увеличить.
Именованные кэши 
 mysql> SET GLOBAL mycache.key_buffer_size = 2 * 1024 * 1024; 
 mysql> CACHE INDEX mytable IN mycache; 
 mysql> LOAD INDEX INTO CACHE mytable;
Особенности кэш запросов 
MySQL 
 Не зависит от движка. 
 Только похожие запросы. Байт в байт. 
- SELECT * from и SELECT * FROM – не одно и то же 
 Подзапросы не кэшируются отдельно. Нужно? Разбей запрос на несколько. 
 NOW(), RAND() и.т.д. мешают кэшу. 
Зло - UPDATE posts SET view_count = view_count+1 WHERE id=10; 
Любое изменение таблицы удаляет из кэша все запросы использующие данную таблицу 
Решение? – Вынеси счетчик отдельно
Что замерять с key cache? 
 Hit ratio – эффективность использования и % заполнения буфера 
 Misses – не попадание в кэш. Зайцев говорит полезнее смотреть сюда =) 
100 - Key_reads * 100 / Key_read_requests 
100 – 50529 * 100 / 58224057 = 99,91 Hit ratio 
Misses 
Key_reads / uptime 
50529 / 94162 = 0,5 … 1
Размер имеет значение. 
 innodb_buffer_pool_size 
- Кэшируются и данные и индексы. Отдавай все 
- Сервер: 50-70% памяти. 16гб – 12-14гб 
- Локал: 25-50% памяти 2гб – 500мб 
- 2-2,5гб для 32бит 
 innodb_log_file_size 
- 5М по умолчанию – «хаха» 
- Большой лог быстрее запись. Не нужно делать кусками. 
- Сначала записывает в лог-файл, то что будет делать, затем делает. Если падает 
смотрит в лог-файл и завершает. 
- Чем больше значение, тем меньше время восстановления. Поэтому 256M хватит
Как работает InnoDB bufer pool 
 innodb_buffer_pool_size
InnoDB 
 Innodb_log_buffer_size – буфер для innodb_log_file 
- Чем меньше, тем чаще идет flush на диск, соответственно медленно работаем 
- 4-8М обычно достаточно 
 innodb_flush_log_at_trx_commit=1 (default) 
- InnoDB такой тормоз! Так ли это? Смотри дефолтное значение 
- 1 – при каждом insert, update идет запись на диск. Buffer then flush immediately 
- 2 – данные пишутся в буфер и flush примерно 1 раз в секунду. Good! 
 Innodb_file_per_table – каждая таблица в отдельном файле 
 Импорт 1-2 часа 12МБ, 0,5-1минут с настройками.
Как и что мониторить? 
 EXPLAIN. EXPLAIN + UPDATE = EXPLAIN SELECT 
 SHOW FULL PROCESSLIST. Попадание 9 из 10-и. 
 Логирование медленных запросов 
 long_query_time 
 Log_slow_queries 
 Log_queries_not_using_indexes
Что мы должны знать? 
SHOW VARIABLES SHOW STATUS 
 Манипуляция c MySQL сервером осуществляется через System Variables 
- mysql> SHOW [GLOBAL|SESSION] VARIABLES [LIKE "string"]; 
- SET [GLOBAL] <variable>=<value> 
- устанавливается через my.cnf 
http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html 
 SHOW STATUS [like “string”] – показывает чем вообще система занимается, занималась. 
http://dev.mysql.com/doc/refman/5.0/en/server-status-variables.html
Show status 
 Если значение Opened_tables велико, возможно, что значение 
переменной table_cache слишком мало. 
 Если значение Key_reads велико, возможно, что значение 
переменной key_buffer_size слишком мало. Читает с диска. 
Key_reads/Key_read_requests = Частота успешных обращений к кэшу 
Если значение Created_tmp_disk_tables велико, возможно, необходимо 
увеличить значение переменной tmp_table_size, чтобы временные 
таблицы располагались в памяти, а не на жестком диске 
http://www.mysql.ru/docs/man/SHOW_STATUS.html
Наши IDE
Navicat, HeidiSQL
MySQL Tuning Primer 
 tuning-primer.sh - https://launchpad.net/mysql-tuning-primer 
MAX CONNECTIONS 
Current max_connections = 200 
Current threads_connected = 7 
Historic max_used_connections = 7 
The number of used connections is 3% of the configured maximum. 
You are using less than 10% of your configured max_connections. 
TABLE CACHE 
Current table_cache value = 256 tables 
You have a total of 135 tables 
You have 137 open tables. 
The table_cache value seems to be fine
Оптимизация схемы. Size does 
matter 
 Использование подходящих типов данных, меньше лучше. Быстрее. 
Занимают меньше места на диске, в памяти, в кэше процессора. 
 Возраст это tinyint а не varchar 
Сравнение целых чисел дешевле сравнения символов. 
Зайцев говорит избегайте Null, нужно Not Null. Усложняются индексы, 
статистика индексов 
 DATETIME vs TIMESTAMP (hollywar?) – можно хранить один и тот же тип данных. 
TIMESTAMP – вдвое меньше места, 
позволяет работать с часовыми поясами. Есть «–».
Оптимизация схемы 
VARCHAR vs CHAR 
 VARCHAR – переменная длинна. Столько места сколько необходимо. (V<255)? +1 : +2 (байта) 
 CHAR – полезен при коротких записях. 4inst: md5(). Фикс длинны - не подвержена фрагментации 
 VARCHAR(1), CHAR(1) – (Y,N) – 2 байта и 1 байт соответственно - в однобайтовой кодировке канеш. 
 ENUM – каждое значение = целое число. В действительности хранятся целые числа, а не строки. 
ENUM(‘fish’,’apple’,’dog’); SELECT e+1; // 2,3,4 
ENUM(‘1’,’3’,’2’) - INSERT VALUES(1,2,3) – SELECT e+1 // 2,4,3
Оптимизация схемы 
Как хранить IP? 
 IP – не строка, а 32-битное беззнаковое число. Точки лишь для удобства. 
 IP - VARCHAR? Bad. Храним как беззнаковое целое число. 
- INET_ATON() и INET_NTOA() 
и.т.д. «Кури доки» В.В.
Procedure ANALYZE() 
SELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max_elements,[max_memory]])
Партиционирование 
 ? Разбиение больших таблиц на логические части по выбранным критериям 
 1 таблица, физически разные файлы. В MyISAM по 3 на каждую партицию. 
SELECT * FROM orders_range WHERE order_date='2009-08-01'; 
 Table - orders_range3 
 Index - p_2008
Репликация 
 Масштабирование вертикальное; масштабирование горизонтальное. 
 Master – пиши, slave – читай. 
 Binary log 
 1 слейв - 1 мастер, 1 мастер – 1..* реплик 
 Мастер пишет изменения в бинарный лог 
 Слейв стягивает себе бинарный лог и последовательно запускает запросы
Чем хороша? 
 Дополнительные индексы. Можно одни на мастере, другие на реплике 
 Разные движки. Fulltext индексы. Master – InnoDB, Slave – MyISAM 
 Производительность и масштабируемость 
 Отказоустойчивость. 
- Если отказала реплика, читай с мастера 
 Резервное копирование данных 
- Останови реплику, сделай с нее mysqldump
Настройка мастера 
IP мастера - 192.168.1.101, IP реплики - 192.168.1.102 
 Настроить сервер 
 Задать права 
Мастер: 
[mysqld]: 
server-id = 1 #уникальный ID сервера 
log-bin = /var/lib/mysql/mysql-bin #путь для бинарных логов 
replicate-do-db = testdb #имя БД для репликации 
mysql@master> GRANT replication slave ON "testdb".* TO "replication"@"192.168.1.102" 
IDENTIFIED BY "password"; 
restart
Настройка реплики 
[mysqld]: 
server-id = 2 
relay-log = /var/lib/mysql/mysql-relay-bin 
relay-log-index = /var/lib/mysql/mysql-relay-bin.index 
replicate-do-db = testdb 
mysql@replica> CHANGE MASTER TO MASTER_HOST = "192.168.1.101 ", 
MASTER_USER = "replication ", MASTER_PASSWORD = "password ", 
MASTER_LOG_FILE = "mysql-bin.000003 ", MASTER_LOG_POS = 98; 
mysql@replica> start slave; 
Значения MASTER_LOG_FILE и MASTER_LOG_POS берем с мастера.
Балансировка 
 Round Robin DNS 
 NGINX. 
- Понятие «обратное проксирование». 
- Значение proxy_pass 
- Алгоритм “Round-Robin” (Привет «Вконтакте») 
- nslookup mail.ru 
 Модуль - ngx_http_upstream_module.
upstream highload /*myCloudName*/ { 
server 192.168.0.1 [weight=3] [max_fails=3] [fail_timeout=60]; 
server 192.168.0.2 [max_fails=3] [fail_timeout=60]; 
server 192.168.0.3 [weight=2] [max_fails=3] [fail_timeout=60]; 
} 
server { 
listen 89.252.34.107:80; 
server_name highload.uk; 
location / { 
proxy_pass http:// highload/; 
proxy_next_upstream error timeout invalid_header http_500 http_503; 
} 
}
Что читать? 
 Справочное руководство. 
 www.mysqlperformanceblog.com

MySQL Optimization. Russian

  • 1.
  • 2.
    Не будем говоритьо…  Железе  Академическом составляющим MySQL или то, что можно легко найти почитать в интернете (triggers, stored procedures, views…).  Движках (Data engines)  Партиционировании (Partitioning)  Шардинге (Sharding)
  • 3.
    О чем будемговорить?  О чем должен знать каждый разработчик?  Что такое индексы и как их правильно использовать  Базовые настройки MySQL my.cnf (my.ini)  Системные переменные (System Variables) и как ими манипулировать  Мониторинг сервера БД на узкие места  Оптимизация запросов к БД  Знаем ли мы фичи наших IDE? HeidiSQL, Navicat.  Репликации  О чем нибудь да поговорим. PHP, byte code, gzip.
  • 4.
    Индексы  Почемусначала об индексах?  Что это такое вообще? Обычно работаем с B tree индексами, о них и поговорим
  • 5.
    Принцип работы Btree https://bubbl.us/  Отсортированы по порядку  Легко делать поиск  Левый крайний нод – min value  Правый крайний нод – max value  Левный нод не будет иметь значение больше или равно чем родитель (X).  Правый нод - минимальное значение - это Х. Будет больше или равно X * Ключи хранятся в индекском файле упорядоченном по принципу Сбаларнсированного бинарного дерева
  • 6.
    Алгоритм поиска Linear(by sequence) Sorted 4 binary search
  • 7.
    Поиск по индексу Ищем id-354 48=354? false 48<354? true 354? false
  • 8.
    Поиск по индксу Ищем id-354 354? true
  • 9.
    Пример B+ дерева,связывающего ключи 1-7 с данными d1-d7. Связи (выделены красным) позволяют быстро обходить дерево в порядке возрастания ключей. Каждый листовой узел содержит указатель на следующий для ускорения обхода.
  • 10.
    Забегаем вперед. EXPLAIN Как посмотреть какой индекс используется? EXPLAIN <select query> 3 интересных поля:  Используемый ключь  Количество проверяемых столбцов. Нужно стараться минимизировать.  Экстра. То что делает БД в процессе исполнения запроса. Хорошо: Using index, Плохо: Using filesort, create tmp tbl, create tmp tbl on disk
  • 11.
    Практика, самая первая+ EXPLAIN  SELECT * FROM t WHERE t.a*=x SELECT id FROM mytest where id4=80 Query time 0.073s Query time 0.002s
  • 12.
    Далее…  SELECT* FROM t WHERE t.a=x LIMIT 10  SELECT * FROM t WHERE t.a=x ORDER BY t.b LIMIT 10 Query time 0.060s
  • 13.
    Еще…  MySQLне знает как использовать 2 разных индекса одной таблицы.  Решение? Композиционный ключь. ALTER TABLE mytest ADD INDEX ixId23(id2,id3);  Индекс(Фамилия, имя) – составной ключь. Нельзя искать сначала И, потом Ф. Ф потом И.  “Using filesort” – плохо. sort_buffer_size –2M (default ) Тада!  Обратная сортировка DESC не меняет сложность запроса  Индекс (А,B) типо= индекс (A). А можно удалить
  • 14.
    Еще чуть обиндексах Индекс(A,B,C) позволяет: WHERE A=10 AND B>10; WHERE A=10 AND B=11 AND C=12; WHERE A=10 AND B=11 ORDER BY C; не позволяет: WHERE B=10; WHERE A=10 AND B>10 AND C>10 SELECT... WHERE func(idx)=20 - не будет использовать SELECT... WHERE idx = func(20) - может использовать индекс
  • 15.
    Ах да… Существуетграничное условие, начиная с которого использование индекса начинает проигрывать последовательному сканированию всей таблицы. Происходит это тогда, когда количество выбираемых с помощью индекса записей больше определенного процента (~30% нужно найти в справочнике точную цифру) от общего количества записей в таблице. Не нужно индексировать все подряд. MySQL все равно выберет какой-то один, но зато вы проиграете на insert, update.
  • 16.
    По-сложнее. Пагинатор Все плохо  SELECT * FROM t WHERE t.a=x LIMIT 1000,10 Handler_read_next = 1009  Может хостер не виноват?  Google, Яндекс и другие десятки поисковиков.
  • 17.
    Как решить? EXPLAINврет!  SELECT id FROM mytest WHERE id>1000 ORDER BY id LIMIT 10  Что говорит Handler_read_next? - 9!
  • 18.
    Чуть сложнее 3 условия WHERE и сортировка SELECT * FROM t WHERE t.a=x AND t.b=y AND t.c>z ORDER BY t.d Какой индекс будет оптимальным, Abc, bcd, abd?  Abc, abd. Индексы не любят когда над ними производятся функкции и выражения  A и B можно менять местами, математические действия всегда в конце.
  • 19.
    Ладно. Highload Умный человек сказал «Преждевременная оптимизация – корень всех зол»  Есть проект  Нагрузка выросла. Клиенты ругаются на производительность.  Что можем сделать на уровне MySQL?
  • 20.
    Лог медленных запросов  Log_slow_queries; long_query_time=1 долгие запросы  Log_queries_not_using_indexes запросы не использующие индексы  Shell> Mysqldumpslow  Всевозможные патчи mysqlsla, mysql_parse_slow etc http://www.mysqlperformanceblog.com
  • 21.
    Тюнинг My.cnf (my.ini)  Настройки по умолчанию – плохо  Основа: Использование памяти лучше чем использование диска.  Что важнее? Настройка потребления памяти  Не пытайтесь тюнить все, для большинства приложении нужно изменить всего несколько параметров
  • 22.
    Хороший тон тюнинга.Правила  Никогда не делать изменения сначала на продакшне  Иметь хорошие инструменты для бенчмарка  Одно изменение за одно время  В голове перекиньте возможные изменения  Пробуйте каждое изменение отдельно  Пробуйте в комбинации 2, потом 3 изменении итд  Мониторить результат Время за один запрос, Среднее время запроса  Задокументируйте
  • 23.
    Важные параметры key_buffer_size – кэш индексов MyISAM - Используется для временных таблиц даже если все Innodb - 30% если только MyISAM, 32M если наоборот. - Временные таблицы в MyISAM - Данные MyISAM не кеширует, они в кэше ОС  table_cache – число открытых таблиц - См рост opened_tables  query_cache_size – Внутренний кэш MySQL - Если запросы не менялись, результат берется из кэша. - Может быть полезен если нет умного кэширования. - 32М обычно достаточно.
  • 24.
    Как работает keycache  На чтение. Смотрит в буфер, если есть возвращает, если нет считывает MYI файл  На запись. Пробивает индекс, убирает все ключи. Наблюдайте за переменными состояния Key_reads и Key_read_requests, отношение Key_reads/Key_read_requests должно быть как можно меньше (< 0,01). Если это отношение велико, то размер буфера стоит увеличить.
  • 25.
    Именованные кэши mysql> SET GLOBAL mycache.key_buffer_size = 2 * 1024 * 1024;  mysql> CACHE INDEX mytable IN mycache;  mysql> LOAD INDEX INTO CACHE mytable;
  • 26.
    Особенности кэш запросов MySQL  Не зависит от движка.  Только похожие запросы. Байт в байт. - SELECT * from и SELECT * FROM – не одно и то же  Подзапросы не кэшируются отдельно. Нужно? Разбей запрос на несколько.  NOW(), RAND() и.т.д. мешают кэшу. Зло - UPDATE posts SET view_count = view_count+1 WHERE id=10; Любое изменение таблицы удаляет из кэша все запросы использующие данную таблицу Решение? – Вынеси счетчик отдельно
  • 27.
    Что замерять сkey cache?  Hit ratio – эффективность использования и % заполнения буфера  Misses – не попадание в кэш. Зайцев говорит полезнее смотреть сюда =) 100 - Key_reads * 100 / Key_read_requests 100 – 50529 * 100 / 58224057 = 99,91 Hit ratio Misses Key_reads / uptime 50529 / 94162 = 0,5 … 1
  • 28.
    Размер имеет значение.  innodb_buffer_pool_size - Кэшируются и данные и индексы. Отдавай все - Сервер: 50-70% памяти. 16гб – 12-14гб - Локал: 25-50% памяти 2гб – 500мб - 2-2,5гб для 32бит  innodb_log_file_size - 5М по умолчанию – «хаха» - Большой лог быстрее запись. Не нужно делать кусками. - Сначала записывает в лог-файл, то что будет делать, затем делает. Если падает смотрит в лог-файл и завершает. - Чем больше значение, тем меньше время восстановления. Поэтому 256M хватит
  • 29.
    Как работает InnoDBbufer pool  innodb_buffer_pool_size
  • 30.
    InnoDB  Innodb_log_buffer_size– буфер для innodb_log_file - Чем меньше, тем чаще идет flush на диск, соответственно медленно работаем - 4-8М обычно достаточно  innodb_flush_log_at_trx_commit=1 (default) - InnoDB такой тормоз! Так ли это? Смотри дефолтное значение - 1 – при каждом insert, update идет запись на диск. Buffer then flush immediately - 2 – данные пишутся в буфер и flush примерно 1 раз в секунду. Good!  Innodb_file_per_table – каждая таблица в отдельном файле  Импорт 1-2 часа 12МБ, 0,5-1минут с настройками.
  • 31.
    Как и чтомониторить?  EXPLAIN. EXPLAIN + UPDATE = EXPLAIN SELECT  SHOW FULL PROCESSLIST. Попадание 9 из 10-и.  Логирование медленных запросов  long_query_time  Log_slow_queries  Log_queries_not_using_indexes
  • 32.
    Что мы должнызнать? SHOW VARIABLES SHOW STATUS  Манипуляция c MySQL сервером осуществляется через System Variables - mysql> SHOW [GLOBAL|SESSION] VARIABLES [LIKE "string"]; - SET [GLOBAL] <variable>=<value> - устанавливается через my.cnf http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html  SHOW STATUS [like “string”] – показывает чем вообще система занимается, занималась. http://dev.mysql.com/doc/refman/5.0/en/server-status-variables.html
  • 33.
    Show status Если значение Opened_tables велико, возможно, что значение переменной table_cache слишком мало.  Если значение Key_reads велико, возможно, что значение переменной key_buffer_size слишком мало. Читает с диска. Key_reads/Key_read_requests = Частота успешных обращений к кэшу Если значение Created_tmp_disk_tables велико, возможно, необходимо увеличить значение переменной tmp_table_size, чтобы временные таблицы располагались в памяти, а не на жестком диске http://www.mysql.ru/docs/man/SHOW_STATUS.html
  • 34.
  • 35.
  • 36.
    MySQL Tuning Primer  tuning-primer.sh - https://launchpad.net/mysql-tuning-primer MAX CONNECTIONS Current max_connections = 200 Current threads_connected = 7 Historic max_used_connections = 7 The number of used connections is 3% of the configured maximum. You are using less than 10% of your configured max_connections. TABLE CACHE Current table_cache value = 256 tables You have a total of 135 tables You have 137 open tables. The table_cache value seems to be fine
  • 37.
    Оптимизация схемы. Sizedoes matter  Использование подходящих типов данных, меньше лучше. Быстрее. Занимают меньше места на диске, в памяти, в кэше процессора.  Возраст это tinyint а не varchar Сравнение целых чисел дешевле сравнения символов. Зайцев говорит избегайте Null, нужно Not Null. Усложняются индексы, статистика индексов  DATETIME vs TIMESTAMP (hollywar?) – можно хранить один и тот же тип данных. TIMESTAMP – вдвое меньше места, позволяет работать с часовыми поясами. Есть «–».
  • 38.
    Оптимизация схемы VARCHARvs CHAR  VARCHAR – переменная длинна. Столько места сколько необходимо. (V<255)? +1 : +2 (байта)  CHAR – полезен при коротких записях. 4inst: md5(). Фикс длинны - не подвержена фрагментации  VARCHAR(1), CHAR(1) – (Y,N) – 2 байта и 1 байт соответственно - в однобайтовой кодировке канеш.  ENUM – каждое значение = целое число. В действительности хранятся целые числа, а не строки. ENUM(‘fish’,’apple’,’dog’); SELECT e+1; // 2,3,4 ENUM(‘1’,’3’,’2’) - INSERT VALUES(1,2,3) – SELECT e+1 // 2,4,3
  • 39.
    Оптимизация схемы Какхранить IP?  IP – не строка, а 32-битное беззнаковое число. Точки лишь для удобства.  IP - VARCHAR? Bad. Храним как беззнаковое целое число. - INET_ATON() и INET_NTOA() и.т.д. «Кури доки» В.В.
  • 40.
    Procedure ANALYZE() SELECT... FROM ... WHERE ... PROCEDURE ANALYSE([max_elements,[max_memory]])
  • 41.
    Партиционирование  ?Разбиение больших таблиц на логические части по выбранным критериям  1 таблица, физически разные файлы. В MyISAM по 3 на каждую партицию. SELECT * FROM orders_range WHERE order_date='2009-08-01';  Table - orders_range3  Index - p_2008
  • 42.
    Репликация  Масштабированиевертикальное; масштабирование горизонтальное.  Master – пиши, slave – читай.  Binary log  1 слейв - 1 мастер, 1 мастер – 1..* реплик  Мастер пишет изменения в бинарный лог  Слейв стягивает себе бинарный лог и последовательно запускает запросы
  • 43.
    Чем хороша? Дополнительные индексы. Можно одни на мастере, другие на реплике  Разные движки. Fulltext индексы. Master – InnoDB, Slave – MyISAM  Производительность и масштабируемость  Отказоустойчивость. - Если отказала реплика, читай с мастера  Резервное копирование данных - Останови реплику, сделай с нее mysqldump
  • 44.
    Настройка мастера IPмастера - 192.168.1.101, IP реплики - 192.168.1.102  Настроить сервер  Задать права Мастер: [mysqld]: server-id = 1 #уникальный ID сервера log-bin = /var/lib/mysql/mysql-bin #путь для бинарных логов replicate-do-db = testdb #имя БД для репликации mysql@master> GRANT replication slave ON "testdb".* TO "replication"@"192.168.1.102" IDENTIFIED BY "password"; restart
  • 45.
    Настройка реплики [mysqld]: server-id = 2 relay-log = /var/lib/mysql/mysql-relay-bin relay-log-index = /var/lib/mysql/mysql-relay-bin.index replicate-do-db = testdb mysql@replica> CHANGE MASTER TO MASTER_HOST = "192.168.1.101 ", MASTER_USER = "replication ", MASTER_PASSWORD = "password ", MASTER_LOG_FILE = "mysql-bin.000003 ", MASTER_LOG_POS = 98; mysql@replica> start slave; Значения MASTER_LOG_FILE и MASTER_LOG_POS берем с мастера.
  • 46.
    Балансировка  RoundRobin DNS  NGINX. - Понятие «обратное проксирование». - Значение proxy_pass - Алгоритм “Round-Robin” (Привет «Вконтакте») - nslookup mail.ru  Модуль - ngx_http_upstream_module.
  • 47.
    upstream highload /*myCloudName*/{ server 192.168.0.1 [weight=3] [max_fails=3] [fail_timeout=60]; server 192.168.0.2 [max_fails=3] [fail_timeout=60]; server 192.168.0.3 [weight=2] [max_fails=3] [fail_timeout=60]; } server { listen 89.252.34.107:80; server_name highload.uk; location / { proxy_pass http:// highload/; proxy_next_upstream error timeout invalid_header http_500 http_503; } }
  • 48.
    Что читать? Справочное руководство.  www.mysqlperformanceblog.com