SlideShare a Scribd company logo
Сергей  Аверин
То,  что  вы  хотели  знать  о  HandlerSocket,  
но  не  смогли  нагуглить
SQL — это, конечно, круто
SELECT associations2.object_id, associations2.term_id, associations2.cat_ID, associations2.term_taxonomy_id
FROM (SELECT objects_tags.object_id, objects_tags.term_id, wp_cb_tags2cats.cat_ID, categories.term_taxonomy_id
FROM (SELECT wp_term_relationships.object_id, wp_term_taxonomy.term_id, wp_term_taxonomy.term_taxonomy_id
FROM wp_term_relationships
LEFT JOIN wp_term_taxonomy ON wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
ORDER BY object_id ASC, term_id ASC)
AS objects_tags
LEFT JOIN wp_cb_tags2cats ON objects_tags.term_id = wp_cb_tags2cats.tag_ID
LEFT JOIN (SELECT wp_term_relationships.object_id, wp_term_taxonomy.term_id as cat_ID, wp_term_taxonomy.term_taxonomy_id
FROM wp_term_relationships
LEFT JOIN wp_term_taxonomy ON wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id
WHERE wp_term_taxonomy.taxonomy = 'category'
GROUP BY object_id, cat_ID, term_taxonomy_id
ORDER BY object_id, cat_ID, term_taxonomy_id)
AS categories on wp_cb_tags2cats.cat_ID = categories.term_id
WHERE objects_tags.term_id = wp_cb_tags2cats.tag_ID
GROUP BY object_id, term_id, cat_ID, term_taxonomy_id
ORDER BY object_id ASC, term_id ASC, cat_ID ASC)
AS associations2
LEFT JOIN categories ON associations2.object_id = categories.object_id
WHERE associations2.cat_ID <> categories.cat_ID
GROUP BY object_id, term_id, cat_ID, term_taxonomy_id
ORDER BY object_id, term_id, cat_ID, term_taxonomy_id

И очень сложно
•
•
•
•
•
•

Групповые функции
Подзапросы
JOIN’ы
Навороченные WHERE-условия
Транзакции и блокировки
и т. д.

С кучей прибамбасов
Но большинство запросов простые
SELECT `email` FROM `users` WHERE `id` = 1

Примерно такие
SELECT `email` FROM `users` WHERE `id` = 1

Примерно такие
SELECT `email` FROM `users` WHERE `id` = 1

Но можно проще
Что такое Handlersocket
•
•
•

MySQL plugin низкоуровневого доступа к InnoDB/XtraDB
Открывает отдельные порты
Имеет свой протокол и набор команд
SQL не поддерживает
Совсем
Плюсы
•
•
•
•
•
•
•

Скорость
Пакетная обработка операций
Компактный протокол
Выдерживает 10000+ соединений
Не отменяет обычный SQL
Совместим с репликацией
Из коробки идет с Percona Server
Поэтому
не нужен memcache
больше свободной памяти
нет дублирования данных
теперь данные консистентны
Плюсы
•
•
•
•
•
•
•

Скорость
Пакетная обработка операций
Компактный протокол
Выдерживает 10000+ соединений
Не отменяет обычный SQL
Совместим с репликацией
Из коробки идет с Percona Server

Минусы
•

Глючит с не-InnoDB/XtraDB
хранилищами

•

Нет транзакций, хранимых
процедур

•

Некоторый базовый функционал
MySQL не поддерживается

•
•
•

Нет коммерческой поддержки
Немного незрелый продукт
Конфликтует с DDL-командами и
LOCK TABLES
Иногда глючит
и еще...

•
•

не очень внятная документация
логика работы и протокол иногда
меняются без всякого уведомления
Чем Handlersocket не является
•
•
•
•
•

Не хранилище «ключ–значение»
Не интерфейс бинарного SQL-протокола
Не для сложных запросов
Не для создания/изменения таблиц
Не для хостинга (нет доступа с разграничением прав)
Принцип работы
 То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
Читающий тред

Читает пачку запросов
Лочит базу, получает read view

1 раз на несколько запросов

Выполняет пачку запросов
Разлочивает базу
Возвращает ответы клиентам
Пишущий тред

Читает пачку запросов
Лочит базу, начинает транзакцию

1 раз на несколько запросов

Выполняет пачку запросов
Коммитит, разлочивает базу
Возвращает ответы клиентам
Взаимодействие HS и MySQL
•
•
•
•
•
•

Консистентность соблюдается при доступе через и SQL и HS
HS прекрасно работает с репликацией MySQL
auto_increment поддерживается
Современные версии HS инвалидируют query cache
Система прав и пользователей MySQL в HS не поддерживается
Блокировка таблиц через HS- и SQL-доступ конфликтует
Специально для рядового Кучи
Будьте осторожны с:

•

‘LOCK TABLES ... WRITE’

•

‘ALTER TABLE ...’

XtraBackup тоже не будет работать.
Подсмотрено в интернетах
Кстати, это plugin, поэтому должно работать:
install plugin handlersocket soname
'handlersocket.so';
uninstall plugin handlersocket;
На практике вторая команда обычно вешает базу.
Как его «готовить»
Очень длинная часть...
Установили, сконфигурировали, подключили...

Теперь у вас есть

2

новых открытых порта: 9998, 9999
только для чтения
Протокол
Клиент открывает соединение
Клиент посылает запрос
Сервер посылает ответ
Клиент посылает следующий запрос
...
(1 запрос — 1 ответ)

Можно послать N запросов подряд, придет N ответов в том
же порядке.
Протокол
•
•
•
•
•
•

Бинарный, но похож на текстовый. Telnet — наше все.
Один запрос или ответ — одна строка.
Каждая строка оканчивается n (0x0A).
Каждая строка состоит из набора токенов разделенных t (0x09).
Токен — это или NULL или кодированная строка.
NULL кодируется как 0 (0x00).
Строки
•
•

Пустая строка — это токен нулевой длины

•

Остальные байты не меняются

Каждый байт в диапазоне 0x00–0x0F предваряется 0x01 и
сдвигается на 0x40. (Пример: 0x03 0x01 0x43)

tt или tn означает, что между ними есть пустая строка
Пример команды:
0 t 3 t 0 t f o o t n
0

3

NULL

foo

(

пустая
строка

)
Ошибки:
2 0
тип ошибки, всегда >= 1

1 1 open_table
название ошибки
Команды
Открытие индекса
P <index_id> <db> <table> <index> <columns> [<fcolumns>]

•

<index_id>: любое целое число

•

<db>,<table>,<index>: Имена базы, таблицы и индекса.
Чтобы открыть первичный ключ используйте имя ключа
PRIMARY.

•

<columns>: разделенный запятыми список столбцов, с
которыми вы будете работать

•

<fcolumns>*: разделенный запятыми список столбцов,
которые вы будете использовать для фильтрации
* — опционально
Открытие индекса
P <index_id> <db> <table> <index> <columns> [<fcolumns>]
P

1

test

store

PRIMARY

id,box

fruit

что-то типа prepared statement
SELECT id,box FROM test.store WHERE id=? AND fruit=?
Открытие индекса
P <index_id> <db> <table> <index> <columns> [<fcolumns>]

•

Можно переоткрыть индекс под тем же <index_id> и
возможно другими <db>/<table>/<index>.

•

Можно открывать ту же самую комбинацию <db>, <table>,
<index> несколько раз, и даже с разными <columns>.

•

Команды «закрыть индекс» нет. Индексы закрываются с
прекращением соединения.

•

Много индексов жрет память и тормозит работу.
Старайтесь обойтись < 1000 открытых индексов.

•

Для скорости <index_id> должны быть как можно меньше.
Вставка
<index_id> + <vlen> <v1> ... <vn>

•

<index_id>: номер открытого индекса

•

<vlen>: количество <v1> ... <vn>. Должно быть <= кол-ва
<columns> в открытом индексе.

•

<v1> ... <vn>: данные для вставки в порядке <columns>.
Остальные поля получают значения по умолчанию.

•

Крайне рекомендуется давать данные для всех полей из
<columns>. (подробнее позже)
Вставка
Пример:
P 89 test hs4 PRIMARY warehouse,box,fruit,count
0 1
89 + 4 New York A1 melon 4
last_insert_id
0 1 1
89 + 4 New York A2 melon 4
last_insert_id
0 1 2
Выборка

сломано ;-(

<index_id> <op> <vlen> <v1> ... <vn> [LIM] [IN] [FILTER]

•
•
•

<index_id>: номер открытого индекса

•
•
•
•

<v1> ... <vn>: значения, которые нужно искать в <index>.

<op>: оператор — один из =, <, <=, >, >=
<vlen>: количество <v1> ... <vn>. Должно быть <= кол-ва
<columns> в открытом индексе.
LIM*: выражение OFFSET-LIMIT
IN*: выражение IN
FILTER*,**: выражение FILTER

* — опционально
** — может повторяться
Выборка
Пример:
Выборка одного ряда по id = 3 (одноколоночный индекс)
P 89 test hs2 PRIMARY warehouse,box,fruit,count
0 1
89 = 1 3
0 4 Virginia
кол-во <columns>

A1

grapes

5
Выборка

сломано ;-(

<index_id> <op> <vlen> <v1> ... <vn> [LIM] [IN] [FILTER]
Выражение LIM:
<limit> <offset>

•

Та же логика, что и в SQL(только здесь <limit> должен
включать кол-во пропускаемых рядов)

•

Если в запросе нет этого выражения, подразумевается
<limit> = 1 и <offset> = 0.

•

Накладывается после применения FILTER.
Выборка
Пример:
Выборка 3 рядов начиная с id 2 (одноколоночный индекс)
P 89 test hs2 PRIMARY warehouse,box,fruit,count
0 1
LIM

89 >= 1 2 3 0
0 4 Seattle B1 banana 4
Virginia B2 watermelon 1

Virginia

! обратите внимание: кол-во колонок — 4, а не 12

A1

grapes

5
Выборка

сломано ;-(

<index_id> <op> <vlen> <v1> ... <vn> [LIM] [IN] [FILTER]
Выражение FILTER:
<ftyp> <fop> <fcol> <fval>

•

<ftyp>: F (пропустить неподходящие ряды) или W (завершить на
первом неподходящем ряду)

•
•

<op>: операция, одна из =, !=, <, <=, >, >=

•

<fval>: значение

<fcol>: номер колонки из <fcolumns> (начиная с нуля)
в открытом индексе

Если указано несколько фильтров, они работают через логическое «И».
Изменение/удаление
<index_id> <op> <vlen> <v1> ... <vn> LIM [IN] [FILTER] MOD
То же самое
требуется
сломано
Изменение/удаление

сломано

<index_id> <op> <vlen> <v1> ... <vn> LIM [IN] [FILTER] MOD
Выражение MOD:
<mop> <m1> ... <mn>

•

<mop>: Операция: U, U? (изменение), D, D? (удаление), +, +?
(инкремент), −, −? (декремент). Операции с '?' возвращают
значения до изменения.

•

<m1> ... <mn>: значения полей в порядке <columns>.
Должны быть <= кол-ва <columns> в открытом индексе.
Остальные колонки не изменяются. Должны быть числами
для '+', '−'. Не используются для 'D', 'D?'.
Изменение/удаление
Пример:
Выборка count по id = 8 с увеличением count на 10
P
0

90
1

test

hsmdemo3
LIM

90 =
0 1

1
6

8

1

count до изменения

PRIMARY
MOD

0

+?

10

count
Изменение/удаление
Пример:
Удаление рядов с id > 0 и count > 3
P
0

89
1

test

hsmdemo3

PRIMARY

LIM

89 > 1
0 1 5

0

1000

кол-во удаленных рядов

count

FILTER

0

F

>

0

count

MOD

3

D
SQL – HS аналогии
•

SELECT a,b,c FROM ...

•

Открытие индекса с
<columns>=a,b,c

•
•

... LIMIT 1 OFFSET 0

Выражение LIM

id BETWEEN 1 AND 2

•
•

•

WHERE a < 1 AND b > 2

•

FILTER типа F a<1
+ FILTER типа F b>2

•
•

a IN (...)

•
•

IN выражение (глючит)

SELECT ... FOR UPDATE, UPDATE

Выборка по индексу >= 1
+ FILTER W-типа id <= 2

Изменение с операторами с '?'
Было сложно, да?
Особенности
Поддерживаемые типы данных
•
•
•

Любые типы данных MySQL нормально читаемы через HS

•

ON UPDATE CURRENT_TIMESTAMP не поддерживается

Писать можно все, кроме типа TIMESTAMP
Не умещающиеся по длине данные обрезаются так же,
как через SQL
Кодировки
•

Если вы работаете только с UTF8 — все просто. Просто
соблюдайте стандарт кодирования протокола HS.

•

BLOB-поля — бинарные, читаем то, что писали, никаких
кодировок.

•

Поля с кодировками HS пишет и читает в кодировке столбца.
То есть о кодировках он ничего не знает, строка — это набор
байт.

•

Тем не менее, байты не соответсвующие кодировке, меняются
на символ ‘?’ при вставке.
Сортировка
•

Collation’ы столбца влияют на операции >, >=, <, <= (но не на
фильтры) и порядок, в котором вы получаете ряды ответов.

•
•

HS при выборке читает ряды в порядке их хранения в индексе

•

См. http://www.collation-charts.org/mysql60/

А в MySQL индексы хранятся сортированными согласно
collation’ам столбцов из которых они состоят
Значения по умолчанию
При вставке пропущенные поля получают значения по умолчанию.
P <index_id> <db> <table> <index> <columns> [<fcolumns>]
Относится только к столбцам, не указанным в <columns> при
открытии индекса!

•
•

Всегда передавайте значения для всех полей из <columns>

•

Глючит с типами данных BINARY, ENUM, TIMESTAMP

NULL как значение по умолчанию не работает.
Вместо NULL вставится пустая строка.
Примеры использования в
Use case 1
Справочник забаненных email’ов

Заменили SELECT * FROM ... WHERE name='...' AND domain='...' на выборку через HS
Одна таблица, один сервер на ДЦ. Master-master репликация между ДЦ.
~52 миллиона строк, ~5 Гб
Все данные в памяти. Используем постоянные соединения.
Use case 1
Справочник забаненных email’ов
Dual-core Intel(R) Xeon(R) CPU E5503 @ 2.00 Ггц
60% CPU, LA ~ 0.5
Вставка/обновление идет
через SQL, <10 RPS
Выборка через HS
~1000 RPS, 3 мс на чтение

время в миллисекундах
Use case 2
Persistent хранилище сессий

Хранилище ключ-значение: выбор/изменение/удаление ряда через HS
Периодически удаляем устаревшие данные через SQL
1 таблица, 1 сервер/ДЦ, ~16 млн рядов, ~23 Гб
Все данные в памяти. Используем постоянные соединения.
Use case 2
Persistent хранилище сессий
12-core Intel(R) Xeon(R) CPU X5650 @ 2.67 Ггц8% CPU, LA ~ 5
Вставка: <10 RPS, ~1,2 мс/запрос
Изменение: ~180 RPS, ~1,3 мс/запрос
Выборка: ~3500 RPS, ~0,5 мс/запрос
Изначально было медленнее. После переезда с MySQL/InnoDB на Percona
Server/XtraDB получили ~ 4x прирост производительности.
Use case 3
Шардированное persistent хранилище сессий

Теперь 10 000 таблиц/100 баз, 1 MySQL, 1 сервер
Распределены по случайно сгенерированному хешу
~10 млн рядов, ~20 Гб
Все данные в памяти. Используем постоянные соединения.
Use case 3
Шардированное persistent хранилище сессий
12-core Intel(R) Xeon(R) CPU X5650 @ 2.67 Ггц
8% CPU, LA ~ 5
Вставка: <10 RPS, ~1,3 мс/запрос
Изменение: ~180 RPS, ~1,3 мс/запрос
Выборка: ~3500 RPS, ~1,6 мс/запрос
Среднее время в мс

RPS
И в чем выгода шардинга?
Однотабличное решение работало хорошо, но плохо
справлялось с большой нагрузкой на запись. Одна таблица была
«горячим местом».
Вторая проблема: при росте таблицы скорость работы падает.
Удаляйте ненужные ряды ежедневно.
Попробуйте решение с шардингом и сравните с однотабличным
вариантом в условиях вашего приложения.
Use case 4
Persistent кеш

Заменили memcached на HS из-за того, что реинициализация кеша шла долго.
32 млн рядов, 14 Гб, распределено по 10 000 таблицам, 1 сервер/ДЦ
Только операции ключ-значение: get и set.
Все данные в памяти. Используем постоянные соединения.
Use case 4
Persistent кеш
12-core Intel(R) Xeon(R) CPU X5650 @ 2.67 Ггц
11% CPU, LA ~ 5
Вставка: <10 RPS, ~0,4 мс/запрос
Изменение: <10 RPS, ~0,4 мс/запрос
Выборка: 14500 RPS в пике, ~0,5 мс/запрос
Среднее время в мс

RPS
«Тюнинг»
•

Попробуйте делать шардинг по ключу выборки при
датасетах > 10 млн рядов

•
•

Перейдите на Percona Server/XtraDB
Используйте постоянные соединения при доступе к HS
Про pconnect’ы
Есть одна проблема с постоянными соединениями.
Следующая итерация/реквест наследует ваш открытый сокет.

•

В протоколе HS запросы и ответы не имеют уникальных id,
поэтому их нельзя надежно сопоставить

•

Выбираем key, value где key = '...', проверяем что ключ в
ответе совпадает с ключом в запросе

•

Переоткрываем соединения при синтактических и I/O
ошибках

•

Не допускайте передачи сокета с недочитанными данными к
следующей итерации
С чем еще можно поиграть
•
•
•
•

InnoDB ROW_FORMAT
InnoDB KEY_BLOCK_SIZE
HASH-индексы
Объединение нескольких индексов в один многоколоночный
Финальный аккорд
FAQ
1) Могу ли я использовать одну из библиотек-клиентов для HS
из интернетов или мне обязательно писать свою?
Если вы хотите использовать pconnect’ы то «допилите» существующую библиотеку или напишите
свою так, чтобы решить проблемы, упомянутые тремя слайдами выше. В остальных случаях можно
брать готовые решения.

2) Зачем мне использовать непонятную фигню Handlersocket
вместо нормальной NoSQL БД типа MongoDB или Redis?
1) Для тех, кто использует MySQL и не может отказаться от нее — вы можете часть функционала
перевести на более быстрый доступ через HS, работая с теми же данными консистентно. SQL при
этом никто не отменяет и весь его функционал будет доступен.
2) Если вы можете «вместить» ваше приложение в простой набор команд HS — у вас будет отличный
NoSQL с некоторыми старыми добрыми фичами SQL-мира: сохранность данных, хорошее
масштабирование по ядрам, эффективное хранение данных и т. д.
Полезные ссылки
Клиентские библиотеки
https://github.com/DeNADev/HandlerSocket-Plugin-for-MySQL/blob/master/README
Исходники HS
https://github.com/DeNADev/HandlerSocket-Plugin-for-MySQL/
Документация
https://github.com/DeNADev/HandlerSocket-Plugin-for-MySQL/tree/master/docs-en
Статья от разработчиков HS
http://yoshinorimatsunobu.blogspot.ru/2010/10/using-mysql-as-nosql-story-for.html
Страница о HS у Percona
http://www.percona.com/doc/percona-server/5.5/performance/handlersocket.html
Must-see презентация от автора HS
http://www.slideshare.net/akirahiguchi/handlersocket-20100629en-5698215
Спасибо!
Вопросы?
@ryba_xek
s@averin.ru

Слайды, код, mind map:
http://averin.ru/slides/

More Related Content

PDF
Сергей Аверин, То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
PDF
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...
PDF
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
PDF
Лекция 5. Встроенные коллекции и модуль collections.
PDF
Лекция #5. Введение в язык программирования Python 3
PDF
[JAM 1.1] Clean Code (Paul Malikov)
PDF
Лекция 6. Классы 1.
PPTX
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
Сергей Аверин, То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить / Сергей Авер...
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
Лекция 5. Встроенные коллекции и модуль collections.
Лекция #5. Введение в язык программирования Python 3
[JAM 1.1] Clean Code (Paul Malikov)
Лекция 6. Классы 1.
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"

What's hot (15)

PDF
Лекция 7. Исключения и менеджеры контекста.
PPTX
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
PPTX
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
PDF
Лекция 8. Итераторы, генераторы и модуль itertools.
PPTX
СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...
PPTX
Web осень 2013 лекция 4
DOC
PT MIFI Labsql
PDF
Лекция 12. Быстрее, Python, ещё быстрее.
PDF
Лекция 1. Начало.
PDF
Лекция 2. Всё, что вы хотели знать о функциях в Python.
PDF
Лекция 11. Тестирование.
PPTX
СУБД 2013 Лекция №5 "Определение узких мест"
PPT
PT MIFI Labsql
PDF
Лекция #7. Django ORM
PPTX
Web осень 2013 лекция 8
Лекция 7. Исключения и менеджеры контекста.
kranonitS20 Сергей Бурма. Django - легко, быстро, эффективно
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
Лекция 8. Итераторы, генераторы и модуль itertools.
СУБД 2013 Лекция №4 "Расширенные возможности работы с базами данных. Триггеры...
Web осень 2013 лекция 4
PT MIFI Labsql
Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 1. Начало.
Лекция 2. Всё, что вы хотели знать о функциях в Python.
Лекция 11. Тестирование.
СУБД 2013 Лекция №5 "Определение узких мест"
PT MIFI Labsql
Лекция #7. Django ORM
Web осень 2013 лекция 8
Ad

Viewers also liked (20)

PDF
Researchers - recommendations from AIGLIA2014
PPT
Entreprenuership & Startup for Young Graduates
PDF
Security protocols
PPTX
Keynote -金耀辉--network service in open stack cloud-osap2012_jinyh_v4
PPTX
Am 04 track1--salvatore orlando--openstack-apac-2012-final
PDF
Pm 02 track1-- 魏刚--osac-trusted-computing-pools-in-folsom-v2
PPTX
Docker First Steps
PPT
1 21
PPT
Power Notes Atomic Structure
PDF
市長直轄プロジェクトの設置 2013.11.20.
PDF
Notam Sul/Sudeste - 01-mai-16
PPTX
Opening remarks-dave-profozichv2
PPTX
Romania, my country, Dana B
PPTX
Q4 06
PPTX
Java peresentation new soft
PPT
Power Notes Atomic Structure Day 3
PPT
March on washington john lewis
PDF
FYI - Gems' Art Show 2015
PDF
Notam 21 mai
PDF
Tek13 - Creating Mobile Apps with PHP and Symfony
Researchers - recommendations from AIGLIA2014
Entreprenuership & Startup for Young Graduates
Security protocols
Keynote -金耀辉--network service in open stack cloud-osap2012_jinyh_v4
Am 04 track1--salvatore orlando--openstack-apac-2012-final
Pm 02 track1-- 魏刚--osac-trusted-computing-pools-in-folsom-v2
Docker First Steps
1 21
Power Notes Atomic Structure
市長直轄プロジェクトの設置 2013.11.20.
Notam Sul/Sudeste - 01-mai-16
Opening remarks-dave-profozichv2
Romania, my country, Dana B
Q4 06
Java peresentation new soft
Power Notes Atomic Structure Day 3
March on washington john lewis
FYI - Gems' Art Show 2015
Notam 21 mai
Tek13 - Creating Mobile Apps with PHP and Symfony
Ad

Similar to То, что вы хотели знать о HandlerSocket, но не смогли нагуглить (20)

PDF
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
PDF
MySQL+HandlerSocket=NoSQL
PDF
CodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQL
PDF
Народные средства оптимизации PostgreSQL
PPTX
SQL________________________________.pptx
PPT
поиск узких мест в производительности My sql ботанический определитель. г. ру...
PDF
Troubleshooting my sql_performance_addons
PPTX
Оптимизации скорости выполнения запросов
PDF
Поиск? Sphinx!
PPTX
СУБД осень 2012 лекция 5
PPT
Индексы в MySQL
PDF
Иван Фролков
PDF
#RuPostgresLive 4: как писать и читать сложные SQL-запросы
PDF
Как читать и интерпретировать вывод команды EXPLAIN
PPTX
Query perfomance tuning
PPT
PPTX
MySQL Optimization. Russian
PPTX
СУБД осень 2012 лекция 7
PDF
SQL-ник DevDay. Рубцов. Новое в Percona Server и MariaDB в сравнении с MySQL 5.5
PDF
Андрей Аксёнов, Sphinx Technologies Inc.
То, что вы хотели знать о HandlerSocket, но не смогли нагуглить
MySQL+HandlerSocket=NoSQL
CodeFest 2013. Аверин С. — MySQL+HandlerSocket=NoSQL
Народные средства оптимизации PostgreSQL
SQL________________________________.pptx
поиск узких мест в производительности My sql ботанический определитель. г. ру...
Troubleshooting my sql_performance_addons
Оптимизации скорости выполнения запросов
Поиск? Sphinx!
СУБД осень 2012 лекция 5
Индексы в MySQL
Иван Фролков
#RuPostgresLive 4: как писать и читать сложные SQL-запросы
Как читать и интерпретировать вывод команды EXPLAIN
Query perfomance tuning
MySQL Optimization. Russian
СУБД осень 2012 лекция 7
SQL-ник DevDay. Рубцов. Новое в Percona Server и MariaDB в сравнении с MySQL 5.5
Андрей Аксёнов, Sphinx Technologies Inc.

More from Sergey Xek (17)

PPTX
Формирование технической команды на старте
PDF
Путь к Go на конкретном примере
PDF
Стартап: формирование технической команды
PDF
Ездим на батарейках
PDF
Javascript-фреймворки:
 должен остаться только один
PDF
Mind map для «Архитектура А/Б тестирования: сделай сам»
PDF
Архитектура А/Б тестирования: сделай сам
PDF
Распространенные ошибки применения баз данных
PDF
Badoo Desktop: оптимизация приложения на миллион юзеров онлайн
PDF
Mysql+handlersocket=nosql
PDF
Не все базы данных одинаково полезны
PDF
Распространенные ошибки применения баз данных
PDF
Не все базы данных одинаково полезны
PDF
Badoo Desktop: оптимизация приложения на миллион юзеров онлайн
PDF
Pconnect: граната в руках обезьяны
PDF
Mind map от «Полмиллиона юзеров в онлайне без падений: оптимизация высокона...
PDF
Полмиллиона юзеров в онлайне без падений: оптимизация высоконагруженного se...
Формирование технической команды на старте
Путь к Go на конкретном примере
Стартап: формирование технической команды
Ездим на батарейках
Javascript-фреймворки:
 должен остаться только один
Mind map для «Архитектура А/Б тестирования: сделай сам»
Архитектура А/Б тестирования: сделай сам
Распространенные ошибки применения баз данных
Badoo Desktop: оптимизация приложения на миллион юзеров онлайн
Mysql+handlersocket=nosql
Не все базы данных одинаково полезны
Распространенные ошибки применения баз данных
Не все базы данных одинаково полезны
Badoo Desktop: оптимизация приложения на миллион юзеров онлайн
Pconnect: граната в руках обезьяны
Mind map от «Полмиллиона юзеров в онлайне без падений: оптимизация высокона...
Полмиллиона юзеров в онлайне без падений: оптимизация высоконагруженного se...

То, что вы хотели знать о HandlerSocket, но не смогли нагуглить

  • 1. Сергей  Аверин То,  что  вы  хотели  знать  о  HandlerSocket,   но  не  смогли  нагуглить
  • 2. SQL — это, конечно, круто
  • 3. SELECT associations2.object_id, associations2.term_id, associations2.cat_ID, associations2.term_taxonomy_id FROM (SELECT objects_tags.object_id, objects_tags.term_id, wp_cb_tags2cats.cat_ID, categories.term_taxonomy_id FROM (SELECT wp_term_relationships.object_id, wp_term_taxonomy.term_id, wp_term_taxonomy.term_taxonomy_id FROM wp_term_relationships LEFT JOIN wp_term_taxonomy ON wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id ORDER BY object_id ASC, term_id ASC) AS objects_tags LEFT JOIN wp_cb_tags2cats ON objects_tags.term_id = wp_cb_tags2cats.tag_ID LEFT JOIN (SELECT wp_term_relationships.object_id, wp_term_taxonomy.term_id as cat_ID, wp_term_taxonomy.term_taxonomy_id FROM wp_term_relationships LEFT JOIN wp_term_taxonomy ON wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id WHERE wp_term_taxonomy.taxonomy = 'category' GROUP BY object_id, cat_ID, term_taxonomy_id ORDER BY object_id, cat_ID, term_taxonomy_id) AS categories on wp_cb_tags2cats.cat_ID = categories.term_id WHERE objects_tags.term_id = wp_cb_tags2cats.tag_ID GROUP BY object_id, term_id, cat_ID, term_taxonomy_id ORDER BY object_id ASC, term_id ASC, cat_ID ASC) AS associations2 LEFT JOIN categories ON associations2.object_id = categories.object_id WHERE associations2.cat_ID <> categories.cat_ID GROUP BY object_id, term_id, cat_ID, term_taxonomy_id ORDER BY object_id, term_id, cat_ID, term_taxonomy_id И очень сложно
  • 6. SELECT `email` FROM `users` WHERE `id` = 1 Примерно такие
  • 7. SELECT `email` FROM `users` WHERE `id` = 1 Примерно такие
  • 8. SELECT `email` FROM `users` WHERE `id` = 1 Но можно проще
  • 9. Что такое Handlersocket • • • MySQL plugin низкоуровневого доступа к InnoDB/XtraDB Открывает отдельные порты Имеет свой протокол и набор команд
  • 11. Плюсы • • • • • • • Скорость Пакетная обработка операций Компактный протокол Выдерживает 10000+ соединений Не отменяет обычный SQL Совместим с репликацией Из коробки идет с Percona Server
  • 12. Поэтому не нужен memcache больше свободной памяти нет дублирования данных теперь данные консистентны
  • 13. Плюсы • • • • • • • Скорость Пакетная обработка операций Компактный протокол Выдерживает 10000+ соединений Не отменяет обычный SQL Совместим с репликацией Из коробки идет с Percona Server Минусы • Глючит с не-InnoDB/XtraDB хранилищами • Нет транзакций, хранимых процедур • Некоторый базовый функционал MySQL не поддерживается • • • Нет коммерческой поддержки Немного незрелый продукт Конфликтует с DDL-командами и LOCK TABLES
  • 14. Иногда глючит и еще... • • не очень внятная документация логика работы и протокол иногда меняются без всякого уведомления
  • 15. Чем Handlersocket не является • • • • • Не хранилище «ключ–значение» Не интерфейс бинарного SQL-протокола Не для сложных запросов Не для создания/изменения таблиц Не для хостинга (нет доступа с разграничением прав)
  • 18. Читающий тред Читает пачку запросов Лочит базу, получает read view 1 раз на несколько запросов Выполняет пачку запросов Разлочивает базу Возвращает ответы клиентам
  • 19. Пишущий тред Читает пачку запросов Лочит базу, начинает транзакцию 1 раз на несколько запросов Выполняет пачку запросов Коммитит, разлочивает базу Возвращает ответы клиентам
  • 20. Взаимодействие HS и MySQL • • • • • • Консистентность соблюдается при доступе через и SQL и HS HS прекрасно работает с репликацией MySQL auto_increment поддерживается Современные версии HS инвалидируют query cache Система прав и пользователей MySQL в HS не поддерживается Блокировка таблиц через HS- и SQL-доступ конфликтует
  • 21. Специально для рядового Кучи Будьте осторожны с: • ‘LOCK TABLES ... WRITE’ • ‘ALTER TABLE ...’ XtraBackup тоже не будет работать.
  • 22. Подсмотрено в интернетах Кстати, это plugin, поэтому должно работать: install plugin handlersocket soname 'handlersocket.so'; uninstall plugin handlersocket; На практике вторая команда обычно вешает базу.
  • 23. Как его «готовить» Очень длинная часть...
  • 24. Установили, сконфигурировали, подключили... Теперь у вас есть 2 новых открытых порта: 9998, 9999 только для чтения
  • 25. Протокол Клиент открывает соединение Клиент посылает запрос Сервер посылает ответ Клиент посылает следующий запрос ... (1 запрос — 1 ответ) Можно послать N запросов подряд, придет N ответов в том же порядке.
  • 26. Протокол • • • • • • Бинарный, но похож на текстовый. Telnet — наше все. Один запрос или ответ — одна строка. Каждая строка оканчивается n (0x0A). Каждая строка состоит из набора токенов разделенных t (0x09). Токен — это или NULL или кодированная строка. NULL кодируется как 0 (0x00).
  • 27. Строки • • Пустая строка — это токен нулевой длины • Остальные байты не меняются Каждый байт в диапазоне 0x00–0x0F предваряется 0x01 и сдвигается на 0x40. (Пример: 0x03 0x01 0x43) tt или tn означает, что между ними есть пустая строка
  • 28. Пример команды: 0 t 3 t 0 t f o o t n 0 3 NULL foo ( пустая строка )
  • 29. Ошибки: 2 0 тип ошибки, всегда >= 1 1 1 open_table название ошибки
  • 31. Открытие индекса P <index_id> <db> <table> <index> <columns> [<fcolumns>] • <index_id>: любое целое число • <db>,<table>,<index>: Имена базы, таблицы и индекса. Чтобы открыть первичный ключ используйте имя ключа PRIMARY. • <columns>: разделенный запятыми список столбцов, с которыми вы будете работать • <fcolumns>*: разделенный запятыми список столбцов, которые вы будете использовать для фильтрации * — опционально
  • 32. Открытие индекса P <index_id> <db> <table> <index> <columns> [<fcolumns>] P 1 test store PRIMARY id,box fruit что-то типа prepared statement SELECT id,box FROM test.store WHERE id=? AND fruit=?
  • 33. Открытие индекса P <index_id> <db> <table> <index> <columns> [<fcolumns>] • Можно переоткрыть индекс под тем же <index_id> и возможно другими <db>/<table>/<index>. • Можно открывать ту же самую комбинацию <db>, <table>, <index> несколько раз, и даже с разными <columns>. • Команды «закрыть индекс» нет. Индексы закрываются с прекращением соединения. • Много индексов жрет память и тормозит работу. Старайтесь обойтись < 1000 открытых индексов. • Для скорости <index_id> должны быть как можно меньше.
  • 34. Вставка <index_id> + <vlen> <v1> ... <vn> • <index_id>: номер открытого индекса • <vlen>: количество <v1> ... <vn>. Должно быть <= кол-ва <columns> в открытом индексе. • <v1> ... <vn>: данные для вставки в порядке <columns>. Остальные поля получают значения по умолчанию. • Крайне рекомендуется давать данные для всех полей из <columns>. (подробнее позже)
  • 35. Вставка Пример: P 89 test hs4 PRIMARY warehouse,box,fruit,count 0 1 89 + 4 New York A1 melon 4 last_insert_id 0 1 1 89 + 4 New York A2 melon 4 last_insert_id 0 1 2
  • 36. Выборка сломано ;-( <index_id> <op> <vlen> <v1> ... <vn> [LIM] [IN] [FILTER] • • • <index_id>: номер открытого индекса • • • • <v1> ... <vn>: значения, которые нужно искать в <index>. <op>: оператор — один из =, <, <=, >, >= <vlen>: количество <v1> ... <vn>. Должно быть <= кол-ва <columns> в открытом индексе. LIM*: выражение OFFSET-LIMIT IN*: выражение IN FILTER*,**: выражение FILTER * — опционально ** — может повторяться
  • 37. Выборка Пример: Выборка одного ряда по id = 3 (одноколоночный индекс) P 89 test hs2 PRIMARY warehouse,box,fruit,count 0 1 89 = 1 3 0 4 Virginia кол-во <columns> A1 grapes 5
  • 38. Выборка сломано ;-( <index_id> <op> <vlen> <v1> ... <vn> [LIM] [IN] [FILTER] Выражение LIM: <limit> <offset> • Та же логика, что и в SQL(только здесь <limit> должен включать кол-во пропускаемых рядов) • Если в запросе нет этого выражения, подразумевается <limit> = 1 и <offset> = 0. • Накладывается после применения FILTER.
  • 39. Выборка Пример: Выборка 3 рядов начиная с id 2 (одноколоночный индекс) P 89 test hs2 PRIMARY warehouse,box,fruit,count 0 1 LIM 89 >= 1 2 3 0 0 4 Seattle B1 banana 4 Virginia B2 watermelon 1 Virginia ! обратите внимание: кол-во колонок — 4, а не 12 A1 grapes 5
  • 40. Выборка сломано ;-( <index_id> <op> <vlen> <v1> ... <vn> [LIM] [IN] [FILTER] Выражение FILTER: <ftyp> <fop> <fcol> <fval> • <ftyp>: F (пропустить неподходящие ряды) или W (завершить на первом неподходящем ряду) • • <op>: операция, одна из =, !=, <, <=, >, >= • <fval>: значение <fcol>: номер колонки из <fcolumns> (начиная с нуля) в открытом индексе Если указано несколько фильтров, они работают через логическое «И».
  • 41. Изменение/удаление <index_id> <op> <vlen> <v1> ... <vn> LIM [IN] [FILTER] MOD То же самое требуется сломано
  • 42. Изменение/удаление сломано <index_id> <op> <vlen> <v1> ... <vn> LIM [IN] [FILTER] MOD Выражение MOD: <mop> <m1> ... <mn> • <mop>: Операция: U, U? (изменение), D, D? (удаление), +, +? (инкремент), −, −? (декремент). Операции с '?' возвращают значения до изменения. • <m1> ... <mn>: значения полей в порядке <columns>. Должны быть <= кол-ва <columns> в открытом индексе. Остальные колонки не изменяются. Должны быть числами для '+', '−'. Не используются для 'D', 'D?'.
  • 43. Изменение/удаление Пример: Выборка count по id = 8 с увеличением count на 10 P 0 90 1 test hsmdemo3 LIM 90 = 0 1 1 6 8 1 count до изменения PRIMARY MOD 0 +? 10 count
  • 44. Изменение/удаление Пример: Удаление рядов с id > 0 и count > 3 P 0 89 1 test hsmdemo3 PRIMARY LIM 89 > 1 0 1 5 0 1000 кол-во удаленных рядов count FILTER 0 F > 0 count MOD 3 D
  • 45. SQL – HS аналогии • SELECT a,b,c FROM ... • Открытие индекса с <columns>=a,b,c • • ... LIMIT 1 OFFSET 0 Выражение LIM id BETWEEN 1 AND 2 • • • WHERE a < 1 AND b > 2 • FILTER типа F a<1 + FILTER типа F b>2 • • a IN (...) • • IN выражение (глючит) SELECT ... FOR UPDATE, UPDATE Выборка по индексу >= 1 + FILTER W-типа id <= 2 Изменение с операторами с '?'
  • 48. Поддерживаемые типы данных • • • Любые типы данных MySQL нормально читаемы через HS • ON UPDATE CURRENT_TIMESTAMP не поддерживается Писать можно все, кроме типа TIMESTAMP Не умещающиеся по длине данные обрезаются так же, как через SQL
  • 49. Кодировки • Если вы работаете только с UTF8 — все просто. Просто соблюдайте стандарт кодирования протокола HS. • BLOB-поля — бинарные, читаем то, что писали, никаких кодировок. • Поля с кодировками HS пишет и читает в кодировке столбца. То есть о кодировках он ничего не знает, строка — это набор байт. • Тем не менее, байты не соответсвующие кодировке, меняются на символ ‘?’ при вставке.
  • 50. Сортировка • Collation’ы столбца влияют на операции >, >=, <, <= (но не на фильтры) и порядок, в котором вы получаете ряды ответов. • • HS при выборке читает ряды в порядке их хранения в индексе • См. http://www.collation-charts.org/mysql60/ А в MySQL индексы хранятся сортированными согласно collation’ам столбцов из которых они состоят
  • 51. Значения по умолчанию При вставке пропущенные поля получают значения по умолчанию. P <index_id> <db> <table> <index> <columns> [<fcolumns>] Относится только к столбцам, не указанным в <columns> при открытии индекса! • • Всегда передавайте значения для всех полей из <columns> • Глючит с типами данных BINARY, ENUM, TIMESTAMP NULL как значение по умолчанию не работает. Вместо NULL вставится пустая строка.
  • 53. Use case 1 Справочник забаненных email’ов Заменили SELECT * FROM ... WHERE name='...' AND domain='...' на выборку через HS Одна таблица, один сервер на ДЦ. Master-master репликация между ДЦ. ~52 миллиона строк, ~5 Гб Все данные в памяти. Используем постоянные соединения.
  • 54. Use case 1 Справочник забаненных email’ов Dual-core Intel(R) Xeon(R) CPU E5503 @ 2.00 Ггц 60% CPU, LA ~ 0.5 Вставка/обновление идет через SQL, <10 RPS Выборка через HS ~1000 RPS, 3 мс на чтение время в миллисекундах
  • 55. Use case 2 Persistent хранилище сессий Хранилище ключ-значение: выбор/изменение/удаление ряда через HS Периодически удаляем устаревшие данные через SQL 1 таблица, 1 сервер/ДЦ, ~16 млн рядов, ~23 Гб Все данные в памяти. Используем постоянные соединения.
  • 56. Use case 2 Persistent хранилище сессий 12-core Intel(R) Xeon(R) CPU X5650 @ 2.67 Ггц8% CPU, LA ~ 5 Вставка: <10 RPS, ~1,2 мс/запрос Изменение: ~180 RPS, ~1,3 мс/запрос Выборка: ~3500 RPS, ~0,5 мс/запрос Изначально было медленнее. После переезда с MySQL/InnoDB на Percona Server/XtraDB получили ~ 4x прирост производительности.
  • 57. Use case 3 Шардированное persistent хранилище сессий Теперь 10 000 таблиц/100 баз, 1 MySQL, 1 сервер Распределены по случайно сгенерированному хешу ~10 млн рядов, ~20 Гб Все данные в памяти. Используем постоянные соединения.
  • 58. Use case 3 Шардированное persistent хранилище сессий 12-core Intel(R) Xeon(R) CPU X5650 @ 2.67 Ггц 8% CPU, LA ~ 5 Вставка: <10 RPS, ~1,3 мс/запрос Изменение: ~180 RPS, ~1,3 мс/запрос Выборка: ~3500 RPS, ~1,6 мс/запрос
  • 60. И в чем выгода шардинга? Однотабличное решение работало хорошо, но плохо справлялось с большой нагрузкой на запись. Одна таблица была «горячим местом». Вторая проблема: при росте таблицы скорость работы падает. Удаляйте ненужные ряды ежедневно. Попробуйте решение с шардингом и сравните с однотабличным вариантом в условиях вашего приложения.
  • 61. Use case 4 Persistent кеш Заменили memcached на HS из-за того, что реинициализация кеша шла долго. 32 млн рядов, 14 Гб, распределено по 10 000 таблицам, 1 сервер/ДЦ Только операции ключ-значение: get и set. Все данные в памяти. Используем постоянные соединения.
  • 62. Use case 4 Persistent кеш 12-core Intel(R) Xeon(R) CPU X5650 @ 2.67 Ггц 11% CPU, LA ~ 5 Вставка: <10 RPS, ~0,4 мс/запрос Изменение: <10 RPS, ~0,4 мс/запрос Выборка: 14500 RPS в пике, ~0,5 мс/запрос
  • 65. • Попробуйте делать шардинг по ключу выборки при датасетах > 10 млн рядов • • Перейдите на Percona Server/XtraDB Используйте постоянные соединения при доступе к HS
  • 66. Про pconnect’ы Есть одна проблема с постоянными соединениями. Следующая итерация/реквест наследует ваш открытый сокет. • В протоколе HS запросы и ответы не имеют уникальных id, поэтому их нельзя надежно сопоставить • Выбираем key, value где key = '...', проверяем что ключ в ответе совпадает с ключом в запросе • Переоткрываем соединения при синтактических и I/O ошибках • Не допускайте передачи сокета с недочитанными данными к следующей итерации
  • 67. С чем еще можно поиграть • • • • InnoDB ROW_FORMAT InnoDB KEY_BLOCK_SIZE HASH-индексы Объединение нескольких индексов в один многоколоночный
  • 69. FAQ 1) Могу ли я использовать одну из библиотек-клиентов для HS из интернетов или мне обязательно писать свою? Если вы хотите использовать pconnect’ы то «допилите» существующую библиотеку или напишите свою так, чтобы решить проблемы, упомянутые тремя слайдами выше. В остальных случаях можно брать готовые решения. 2) Зачем мне использовать непонятную фигню Handlersocket вместо нормальной NoSQL БД типа MongoDB или Redis? 1) Для тех, кто использует MySQL и не может отказаться от нее — вы можете часть функционала перевести на более быстрый доступ через HS, работая с теми же данными консистентно. SQL при этом никто не отменяет и весь его функционал будет доступен. 2) Если вы можете «вместить» ваше приложение в простой набор команд HS — у вас будет отличный NoSQL с некоторыми старыми добрыми фичами SQL-мира: сохранность данных, хорошее масштабирование по ядрам, эффективное хранение данных и т. д.
  • 70. Полезные ссылки Клиентские библиотеки https://github.com/DeNADev/HandlerSocket-Plugin-for-MySQL/blob/master/README Исходники HS https://github.com/DeNADev/HandlerSocket-Plugin-for-MySQL/ Документация https://github.com/DeNADev/HandlerSocket-Plugin-for-MySQL/tree/master/docs-en Статья от разработчиков HS http://yoshinorimatsunobu.blogspot.ru/2010/10/using-mysql-as-nosql-story-for.html Страница о HS у Percona http://www.percona.com/doc/percona-server/5.5/performance/handlersocket.html Must-see презентация от автора HS http://www.slideshare.net/akirahiguchi/handlersocket-20100629en-5698215