Мое серверное приложение делает несколько подключений к MySQL через отдельные потоки. Каждое соединение вызывает запрос SELECT
и извлекает результат, который приложение затем возвращает к подключенным пользователям.MySQL: выбор выполнения запроса и увеличение времени выборки результатов с количеством подключений
Я пользуюсь InnoDB. К моему удивлению, мне показалось очень странным, что, если я увеличиваю количество подключений к MySQL, производительность запросов ухудшится, и время выборки также увеличится. Ниже приведена таблица.
Эти данные создаются, когда у меня было 3333 записей в таблице MySQL, а запрос SELECT
, основанный на случайных параметрах, предоставленных ему, извлекает около 450 записей из них. Каждая запись содержит около 10 полей, и все они вместе содержат 1,2 КБ данных. (Таким образом, единый SELECT
запрос получает 1,2 * 450 = 540 Кбайт данных в общей сложности)
╔═══════════╦═══════════════╦══════════════╗ ║ Number of ║Query execution║ Result fetch ║ ║connections║ time range ║ time range ║ ║ to MySQL ║ (in seconds) ║ (in seconds) ║ ╠═══════════╬═══════════════╬══════════════╣ ║ 1 ║ 0.02 to 0.06 ║ 0.03 to 0.18 ║ ║ 7 ║ 0.23 to 0.64 ║ 0.54 to 0.74 ║ ║ 17 ║ 0.32 to 1.71 ║ 0.53 to 1.18 ║ ║ 37 ║ 0.37 to 2.01 ║ 0.70 to 1.70 ║ ║ 117 ║ 1.13 to 3.29 ║ 2.48 to 3.25 ║ ╚═══════════╩═══════════════╩══════════════╝
То, что я не понимаю, вот почему MySQL занимает больше времени, когда число подключений к ней увеличивается? Особенно, когда в таблицу не добавляются обновления, MySQL должен обрабатывать запрос SELECT
от каждого соединения в отдельном потоке. Таким образом, одновременная обработка запроса. Следовательно, в идеале не должно быть значительного ухудшения производительности и выборки.
Я не буду возражать, чтобы иметь одно соединение с БД, но поймать, что производительность моего сервера значительно ухудшается. Тысячи пользователей (подключенных к моему серверу) должны будут ждать, пока этот единственный поток не появится.
Пройдя некоторые связанные с этим вопросы, я попытался увеличить innodb_buffer_pool_size
до 1 GB без везения.
Вот мои все InnoDB параметры:
innodb_adaptive_flushing ON
innodb_adaptive_flushing_lwm 10
innodb_adaptive_hash_index ON
innodb_adaptive_max_sleep_delay 150000
innodb_additional_mem_pool_size 2097152
innodb_api_bk_commit_interval 5
innodb_api_disable_rowlock OFF
innodb_api_enable_binlog OFF
innodb_api_enable_mdl OFF
innodb_api_trx_level 0
innodb_autoextend_increment 64
innodb_autoinc_lock_mode 1
innodb_buffer_pool_dump_at_shutdown OFF
innodb_buffer_pool_dump_now OFF
innodb_buffer_pool_filename ib_buffer_pool
innodb_buffer_pool_instances 8
innodb_buffer_pool_load_abort OFF
innodb_buffer_pool_load_at_startup OFF
innodb_buffer_pool_load_now OFF
innodb_buffer_pool_size 1073741824
innodb_change_buffer_max_size 25
innodb_change_buffering all
innodb_checksum_algorithm crc32
innodb_checksums ON
innodb_cmp_per_index_enabled OFF
innodb_commit_concurrency 0
innodb_compression_failure_threshold_pct 5
innodb_compression_level 6
innodb_compression_pad_pct_max 50
innodb_concurrency_tickets 5000
innodb_data_file_path ibdata1:12M:autoextend
innodb_data_home_dir
innodb_disable_sort_file_cache OFF
innodb_doublewrite ON
innodb_fast_shutdown 1
innodb_file_format Antelope
innodb_file_format_check ON
innodb_file_format_max Antelope
innodb_file_per_table ON
innodb_flush_log_at_timeout 1
innodb_flush_log_at_trx_commit 2
innodb_flush_method normal
innodb_flush_neighbors 1
innodb_flushing_avg_loops 30
innodb_force_load_corrupted OFF
innodb_force_recovery 0
innodb_ft_aux_table
innodb_ft_cache_size 8000000
innodb_ft_enable_diag_print OFF
innodb_ft_enable_stopword ON
innodb_ft_max_token_size 84
innodb_ft_min_token_size 3
innodb_ft_num_word_optimize 2000
innodb_ft_result_cache_limit 2000000000
innodb_ft_server_stopword_table
innodb_ft_sort_pll_degree 2
innodb_ft_total_cache_size 640000000
innodb_ft_user_stopword_table
innodb_io_capacity 200
innodb_io_capacity_max 2000
innodb_large_prefix OFF
innodb_lock_wait_timeout 50
innodb_locks_unsafe_for_binlog OFF
innodb_log_buffer_size 268435456
innodb_log_compressed_pages ON
innodb_log_file_size 262144000
innodb_log_files_in_group 2
innodb_log_group_home_dir .\
innodb_lru_scan_depth 1024
innodb_max_dirty_pages_pct 75
innodb_max_dirty_pages_pct_lwm 0
innodb_max_purge_lag 0
innodb_max_purge_lag_delay 0
innodb_mirrored_log_groups 1
innodb_monitor_disable
innodb_monitor_enable
innodb_monitor_reset
innodb_monitor_reset_all
innodb_old_blocks_pct 37
innodb_old_blocks_time 1000
innodb_online_alter_log_max_size 134217728
innodb_open_files 300
innodb_optimize_fulltext_only OFF
innodb_page_size 16384
innodb_print_all_deadlocks OFF
innodb_purge_batch_size 300
innodb_purge_threads 1
innodb_random_read_ahead OFF
innodb_read_ahead_threshold 56
innodb_read_io_threads 64
innodb_read_only OFF
innodb_replication_delay 0
innodb_rollback_on_timeout OFF
innodb_rollback_segments 128
innodb_sort_buffer_size 1048576
innodb_spin_wait_delay 6
innodb_stats_auto_recalc ON
innodb_stats_method nulls_equal
innodb_stats_on_metadata OFF
innodb_stats_persistent ON
innodb_stats_persistent_sample_pages 20
innodb_stats_sample_pages 8
innodb_stats_transient_sample_pages 8
innodb_status_output OFF
innodb_status_output_locks OFF
innodb_strict_mode OFF
innodb_support_xa ON
innodb_sync_array_size 1
innodb_sync_spin_loops 30
innodb_table_locks ON
innodb_thread_concurrency 8
innodb_thread_sleep_delay 0
innodb_undo_directory .
innodb_undo_logs 128
innodb_undo_tablespaces 0
innodb_use_native_aio OFF
innodb_use_sys_malloc ON
innodb_version 5.6.28
innodb_write_io_threads 16
Может кто-то пожалуйста, проливают свет? Меня это раздражает очень долго.
(Примечание: я не упомянул фактический запрос в этом вопросе, потому что запрос немного сложнее, и этот вопрос не о том, что запрос Но речь идет о деградации производительности с увеличением соединений при запросе такой же.)
UPDATE 1
Вот SHOW CREATE TABLE
выход для моих таблиц:
CREATE TABLE `profiles` (
`SRNO` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`HANDLE_FIRST` int(10) unsigned NOT NULL,
`HANDLE_SECOND` bigint(20) unsigned NOT NULL,
`USERID` binary(16) NOT NULL,
`UNIQUESTRING` char(10) NOT NULL,
`CLIENT_VERSION` smallint(5) unsigned NOT NULL,
`ISCONNECTED` bit(1) NOT NULL,
`ISPROFILEPRESENT` bit(1) NOT NULL,
`USERNAME` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`GENDER` tinyint(1) DEFAULT NULL,
`DND` bit(1) DEFAULT NULL,
`STATUS` varchar(128) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`PROFILE_URL` varchar(128) DEFAULT NULL,
PRIMARY KEY (`SRNO`),
UNIQUE KEY `USERID` (`USERID`),
KEY `USERID_INDEX` (`USERID`),
KEY `UNIQUESTRING_INDEX` (`UNIQUESTRING`),
KEY `ISCONNECTED_INDEX` (`ISCONNECTED`),
KEY `ISPROFILEPRESENT_INDEX` (`ISPROFILEPRESENT`)
) ENGINE=InnoDB AUTO_INCREMENT=9250 DEFAULT CHARSET=utf8
CREATE TABLE `blockers` (
`BLOCKER_PROFILE_SRNO` bigint(20) unsigned NOT NULL,
`BLOCKED_PROFILE_SRNO` bigint(20) unsigned NOT NULL,
UNIQUE KEY `BLOCKER_PROFILE_SRNO` (`BLOCKER_PROFILE_SRNO`,`BLOCKED_PROFILE_SRNO`),
KEY `BLOCKER_PROFILE_SRNO_INDEX` (`BLOCKER_PROFILE_SRNO`),
KEY `BLOCKED_PROFILE_SRNO_INDEX` (`BLOCKED_PROFILE_SRNO`),
CONSTRAINT `fk_BlockedIndex` FOREIGN KEY (`BLOCKED_PROFILE_SRNO`) REFERENCES `profiles` (`SRNO`),
CONSTRAINT `fk_BlockerIndex` FOREIGN KEY (`BLOCKER_PROFILE_SRNO`) REFERENCES `profiles` (`SRNO`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
И вот запрос я бегу:
select prfls.*
from profiles as prfls
left outer join blockers as blkr1 on blkr1.blocker_profile_srno = prfls.srno
and blkr1.blocked_profile_srno = 6443
left outer join blockers as blkr2 on blkr2.blocker_profile_srno = 6443
and blkr2.blocked_profile_srno = prfls.srno
where blkr1.blocker_profile_srno is null
and blkr2.blocker_profile_srno is null
and ( (prfls.uniquestring like 'phk5600dcc%')
or (prfls.uniquestring like 'phk5600dcf%')
)
and prfls.isconnected=1
and prfls.isprofilepresent=1
limit 450
Этот запрос по существу подготовленное заявление, где blocked_profile_srno
, blocker_profile_srno
и uniquestring
параметры постоянно меняются для каждого запроса. Однако blocked_profile_srno
и blocker_profile_srno
всегда остаются равными (в приведенном выше запросе их значение равно 6443). Таблица blockers
пуста (я использую ее для использования в будущем, но в настоящее время она не имеет данных)
Когда 117 соединений выполнялись одновременно с запросами, выход SHOW GLOBAL STATUS LIKE 'Threads_running';
был в большинстве случаев 1. Однако иногда он поднимался до 27 ,В то же время, выход SHOW GLOBAL STATUS LIKE 'Max_used_connections';
был 130
UPDATE 2
я могу собрать из Rick James ответа ниже, оптимизирующий запрос уменьшает запрос диапазон времени выполнения. Этот временной диапазон продолжает увеличиваться с количеством подключений, но в пределах допустимого диапазона. Вот почему я принял ответ.
Общее количество выполненных запросов в секунду отличается для различного количества соединений? Сколько ядер вашего процессора? –
Какое оборудование вы используете? –
На самом деле это не высокотехнологичное оборудование. Двойной ядро [email protected] ГГц с 4 ГБ ОЗУ и ОС - Windows 8. – Atul