Начиная с нашего первого поста об оптимизации дескрипторов транзакций, представленного в Percona Server 5.5.30-30.2, и продолжения Дмитрия Кравчука, мы получили большое количество вопросов о том, почему результаты тестов в обоих постах выглядят довольно по-разному. Нам также было любопытно, поэтому мы попытались ответить на этот вопрос, повторив тесты для различных комбинаций аппаратных средств и размеров наборов данных, включая те, которые максимально приближены к среде Дмитрия. Короче говоря, результаты вполне соответствуют нашей первоначальной публикации по всем тестовым комбинациям, подробности см. Ниже.
Вот краткое резюме контекста. В первом посте рассматриваются два случая:
- одиночные
SELECT
запросы делаютPRIMARY KEY
просмотры (ака QPs SysBench режима); - те же запросы, выполняемые внутри транзакций с одним оператором ( режим TPS , см. исходное сообщение о том, почему этот случай актуален).
Дмитрий не коснулся дела № 2 и сосредоточился только на деле № 1. Это идеальный вариант для оптимизации транзакций только для чтения в MySQL 5.6, поскольку все SELECT
запросы в AUTOCOMMIT
режиме по определению являются транзакциями только для чтения, поэтому сервер создает пустой список транзакций при создании представлений для чтения. Однако более общая оптимизация дескрипторов в Percona Server показала довольно близкие результаты в наших тестах. В тестах Димитри масштабируемость Percona Server находится где-то между MySQL 5.5 и MySQL 5.6.
Чтобы лучше понять различия между результатами, мы повторно запустили тесты на нескольких наших боксах. Вы можете найти подробности настройки / конфигурации в самом конце этого поста.
Оборудование:
- HP ProLiant DL380 G6 (8 ядер / 16 нитей процессора)
- Cisco UCS C250 (12 ядер / 24 процессора)
- Dell PowerEdge R720 (16 ядер / 32 процессора)
Все они представляют собой блоки NUMA, но второй имеет более высокую пропускную способность QPI, а третий обладает еще более высокой скоростью QPI (и, следовательно, более быстрой связью между процессами / узлами).
Полученные результаты:
Прежде всего, мы использовали меньший набор данных для этого раунда тестов, поскольку, как сообщается, Дмитрий использовал 8 таблиц с 1М строк в каждой (около 2,1 ГБ) для своих тестов, в то время как в наших первоначальных тестах мы использовали гораздо большую таблицу, 16 таблиц с 5М Строки каждая (около 23 ГБ). Поэтому имеет смысл проверить, имеет ли значение размер набора данных.
Сначала мы исключили NUMA из уравнения. Мы провели тесты на коробке Dell PowerEdge R720 и различных комбинациях процессоров с набором задач. На следующей диаграмме показано сравнение результатов в конфигурации с одним узлом (слева) и с двумя узлами (справа).
Здесь нет ничего удивительного, общая схема согласуется с тем, что мы видели ранее. Обратите внимание, что в конфигурации с одним узлом использовалось 16 потоков (8 ядер на одном сокете x 2 потока на сокет), а во втором — 16 ядер (8 ядер на сокет на узел). Таким образом, этот тест также исключает HT как виновника различия результатов.
Затем мы сравнили результаты по всем 3 блокам, чтобы увидеть, оказывает ли различное оборудование заметное влияние:
Все еще не повезло, все соответствует другим тестам. Есть небольшие различия, например, в первых двух случаях производительность Percona Server даже немного опережает MySQL 5.6.10, но ничего неожиданного.
Поэтому, хотя разница в результатах все еще требует объяснения, я хотел бы выделить один аспект оптимизации дескрипторов, который, как я думал, был объяснен в исходном посте, но, похоже, вызывает много путаницы.
Несмотря на то, что оптимизация транзакций только для чтения в MySQL 5.6 практически исключает конфликты на мьютексе, защищающие список транзакций, ее применимость весьма ограничена. А именно, он требует, чтобы список транзакций был либо пустым, либо очень коротким, что в основном подразумевает полностью доступный только для чтения сервер. Как только количество обновлений в базе данных становится нетривиальным, все SELECT
запросы, даже те, которые участвуют в транзакциях только для чтения, начинают страдать от издержек trx_list, создаваемых одновременными обновлениями.
Как только мы отойдем от этой сферической коровы только для чтения и добавим некоторые обновления данных, ограничение транзакций только для чтения станет очевидным.
В следующем тесте sysbench выполняет 9 первичных ключей, SELECT
за которыми следует UPDATE
инструкция PK в каждом потоке в цикле, что, вероятно, немного ближе к реальной рабочей нагрузке. Это все еще AUTOCOMMIT
режим, поэтому SELECT
s — это транзакции только для чтения, но это мало помогает, потому что, например, для 1024 одновременных потоков каждый SELECT
должен сканировать около 100 транзакций обновления, чтобы создать представление для чтения:
Я надеюсь, что это проливает больше света на настройку наших тестов и уточняет область оптимизации дескрипторов.
Конфигурация сервера:
[mysqld] user=root port=3306 innodb_status_file=0 innodb_data_file_path=ibdata1:100M:autoextend innodb_flush_log_at_trx_commit = 2 innodb_flush_method = O_DIRECT innodb_log_buffer_size = 16M innodb_buffer_pool_size = 52G innodb_log_file_size = 2000M innodb_log_files_in_group = 2 innodb_file_per_table = true innodb_read_io_threads = 8 innodb_write_io_threads = 8 innodb_io_capacity = 2000 max_connections=5000 table_open_cache=5000 query_cache_type=OFF performance_schema=0
разогреть
Для прогрева сервера и загрузки данных и индексов в буферный пул мы используем следующие запросы:
select avg(id) from sbtest$i force key (primary) select count(*) from sbtest$i WHERE k like '%0%'
SysBench-0,5 / Lua:
POINT_SELECT QPS тест
sysbench --num-threads=<1..1024> --test=oltp.lua --oltp_tables_count=8 --oltp-table-size=1000000 --rand-init=on --report-interval=1 --rand-type=uniform --forced-shutdown=1 --max-time=120 --max-requests=0 --percentile=99 --mysql-user=root --mysql-db=sbtest8t1M --mysql-table-engine=INNODB --mysql-socket=/tmp/mysql.sock --oltp-point-selects=1 --oltp-simple-ranges=0 --oltp-sum-ranges=0 --oltp-order-ranges=0 --oltp-distinct-ranges=0 --oltp-skip-trx=on --oltp-test-mode=nontrx --oltp-read-only=off --oltp-index-updates=0 --oltp-non-index-updates=0 run
POINT_SELECT + UPDATE QPS test
sysbench --num-threads=<1..1024> --test=oltp.lua --oltp_tables_count=8 --oltp-table-size=1000000 --rand-init=on --report-interval=1 --rand-type=uniform --forced-shutdown=1 --max-time=120 --max-requests=0 --percentile=99 --mysql-user=root --mysql-db=sbtest8t1M --mysql-table-engine=INNODB --mysql-socket=/tmp/mysql.sock --oltp-point-selects=9 --oltp-simple-ranges=0 --oltp-sum-ranges=0 --oltp-order-ranges=0 --oltp-distinct-ranges=0 --oltp-skip-trx=on --oltp-test-mode=nontrx --oltp-read-only=off --oltp-index-updates=1 --oltp-non-index-updates=0 run