꽤 성가신 문제가 있습니다. INNODB를 기본 데이터베이스 엔진으로 사용하고 중복을 위해 galera-cluster를 사용하기 위해 전자가 필요하므로 MyISAM을 포기하고 싶습니다.
newbb_post
테이블을 새 테이블로 복사하고 (설명 다음에) newbb_innopost
InnoDB로 변경했습니다. 테이블에는 현재 5,390,146
각 항목이 있습니다.
새로 선택한 데이터베이스에서 이러한 선택을 실행하면 (이 시점에서 캐싱이 포함되지 않습니다!) 데이터베이스는 다음 결과를 생성합니다 (전체 출력 생략, 데이터베이스에 결과 정렬을 요구하지 않음).
post.postid, post.attach를 선택하십시오. . . | 5401593 | 0 | | 5401634 | 0 | + --------- + -------- + 62510 행 세트 (0.13 초)
post.postid, post.attach from post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post thread post post post-threadid = 51506; post. post-post에서 post.postid, post.attach에서 newbb_innopost에서 post.threadid = 51506; . . | 5397410 | 0 | | 5397883 | 0 | + --------- + -------- + 62510 행 세트 (1 분 22.19 초)
0.13 초 ~ 86.19 초 (!)
왜 이런 일이 일어나고 있는지 궁금합니다. InnoDB와 관련된 Stackexchange에 대한 답변을 여기에서 읽었으며 일부는 innodb_buffer_pool
설치된 RAM의 80 %로 크기를 늘리는 것을 제안 합니다. 이렇게하면 특정 ID에 대한 초기 쿼리가 적어도 50 배 이상 걸리고 전체 웹 서버를 정지시켜 데이터베이스에 대한 연결 및 쿼리를 대기시키는 문제가 해결되지 않습니다. 나중에 캐시 / 버퍼가 시작될 수 있지만이 데이터베이스에 100.000 개가 넘는 스레드가 있으므로 캐시가 제공 될 모든 관련 쿼리를 보유하지 않을 가능성이 높습니다.
위의 쿼리는 단순하고 (조인 없음) 모든 키가 사용됩니다.
post.postid 선택, post.attach from post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post aspost as post where post.threadid = 51506; + ------ + ------------- + ------- + ------ + --------------- ---------------------------------- + ---------- + ---- ----- + ------- + -------- + ------- + | 아이디 | select_type | 테이블 | 타입 | possible_keys | 열쇠 | key_len | 심판 | 행 | 추가 | + ------ + ------------- + ------- + ------ + --------------- ---------------------------------- + ---------- + ---- ----- + ------- + -------- + ------- + | 1 | 단순 | 게시물 | 심판 | threadid, threadid_2, threadid_visible_dateline | threadid | 4 | const | 120144 | | + ------ + ------------- + ------- + ------ + --------------- ---------------------------------- + ---------- + ---- ----- + ------- + -------- + ------- +
이것은 MyISAM 테이블입니다.
CREATE TABLE`newbb_post` ( `postid` int (10) unsigned NOT NULL AUTO_INCREMENT, `threadid` int (10) unsigned NOT NULL DEFAULT '0', `parentid` int (10) 부호없는 NOT NULL DEFAULT '0', `username` varchar (100) NOT NULL DEFAULT``, `userid` int (10) unsigned NOT NULL DEFAULT '0', `title` varchar (250) NOT NULL DEFAULT '', `dateline` int (10) unsigned NOT NULL DEFAULT '0', `pagetext` 중간 텍스트, `allowsmilie` smallint (6) NOT NULL DEFAULT '0', `showsignature` smallint (6) NOT NULL DEFAULT '0', `ipaddress` varchar (15) NOT NULL DEFAULT``, `iconid` smallint (5) 부호없는 NOT NULL DEFAULT '0', `visible` smallint (6) NOT NULL DEFAULT '0', `attach` smallint (5) 부호없는 NOT NULL DEFAULT '0', `infraction` smallint (5) 부호없는 NOT NULL DEFAULT '0', `reportthreadid` int (10) 부호없는 NOT NULL DEFAULT '0', `importthreadid` bigint (20) NOT NULL DEFAULT '0', `importpostid` bigint (20) NOT NULL DEFAULT '0', `converted_2_utf8` int (11) NOT NULL, `htmlstate` enum ( 'off', 'on', 'on_nl2br') NOT NULL DEFAULT 'on_nl2br', 기본 키 (`postid`), 핵심`threadid` (`threadid`,`userid`), 핵심`importpost_index` (`importpostid`), 키`날짜`(`날짜`), KEY`threadid_2` (`threadid`,`visible`,`dateline`), KEY`converted_2_utf8` (`converted_2_utf8`), KEY`threadid_visible_dateline` (`threadid`,`visible`,`dateline`,`userid`,`postid`), 키`ipaddress` (`ipaddress`), 키`userid` (`userid`,`parentid`), KEY`user_date` (`userid`,`dateline`) ) ENGINE = MyISAM AUTO_INCREMENT = 5402802 기본 문자 세트 = 라틴 1
그리고 이것은 InnoDB 테이블입니다 (정확히 동일합니다).
테이블`newbb_innopost` ( `postid` int (10) unsigned NOT NULL AUTO_INCREMENT, `threadid` int (10) unsigned NOT NULL DEFAULT '0', `parentid` int (10) 부호없는 NOT NULL DEFAULT '0', `username` varchar (100) NOT NULL DEFAULT``, `userid` int (10) unsigned NOT NULL DEFAULT '0', `title` varchar (250) NOT NULL DEFAULT '', `dateline` int (10) unsigned NOT NULL DEFAULT '0', `pagetext` 중간 텍스트, `allowsmilie` smallint (6) NOT NULL DEFAULT '0', `showsignature` smallint (6) NOT NULL DEFAULT '0', `ipaddress` varchar (15) NOT NULL DEFAULT``, `iconid` smallint (5) 부호없는 NOT NULL DEFAULT '0', `visible` smallint (6) NOT NULL DEFAULT '0', `attach` smallint (5) 부호없는 NOT NULL DEFAULT '0', `infraction` smallint (5) 부호없는 NOT NULL DEFAULT '0', `reportthreadid` int (10) 부호없는 NOT NULL DEFAULT '0', `importthreadid` bigint (20) NOT NULL DEFAULT '0', `importpostid` bigint (20) NOT NULL DEFAULT '0', `converted_2_utf8` int (11) NOT NULL, `htmlstate` enum ( 'off', 'on', 'on_nl2br') NOT NULL DEFAULT 'on_nl2br', 기본 키 (`postid`), 핵심`threadid` (`threadid`,`userid`), 핵심`importpost_index` (`importpostid`), 키`날짜`(`날짜`), KEY`threadid_2` (`threadid`,`visible`,`dateline`), KEY`converted_2_utf8` (`converted_2_utf8`), KEY`threadid_visible_dateline` (`threadid`,`visible`,`dateline`,`userid`,`postid`), 키`ipaddress` (`ipaddress`), 키`userid` (`userid`,`parentid`), KEY`user_date` (`userid`,`dateline`) ) ENGINE = InnoDB AUTO_INCREMENT = 5402802 기본 문자 집합 = 라틴 1
32GB RAM이있는 서버 :
서버 버전 : 10.0.12-MariaDB-1 ~ trusty-wsrep-log mariadb.org 바이너리 배포, wsrep_25.10.r4002
모든 innodb_ 변수 설정이 필요한 경우이 게시물에 첨부 할 수 있습니다.
최신 정보:
기본 인덱스와는 별도로 모든 인덱스를 삭제 한 후 결과는 다음과 같습니다.
. . | 5402697 | 0 | | 5402759 | 0 | + --------- + -------- + 62510 행 세트 (29.74 초)
post.postid 선택, post.attach from post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post aspost as post where post.threadid = 51506; + ------ + ------------- + ------- + ------ + --------------- -+ ------ + --------- + ------ + ----------- + --------------- + | 아이디 | select_type | 테이블 | 타입 | possible_keys | 열쇠 | key_len | 심판 | 행 | 추가 | + ------ + ------------- + ------- + ------ + --------------- -+ ------ + --------- + ------ + ----------- + --------------- + | 1 | 단순 | 게시물 | 모두 | NULL | NULL | NULL | NULL | 5909836 | 사용하여 | + ------ + ------------- + ------- + ------ + --------------- -+ ------ + --------- + ------ + ----------- + --------------- + 1 행 세트 (0.00 초)
이 후 믹스, threadid에 하나의 인덱스를 다시 추가하면 결과는 다음과 같습니다.
. . | 5402697 | 0 | | 5402759 | 0 | + --------- + -------- + 62510 행 세트 (11.58 초)
post.postid 선택, post.attach from post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post post aspost as post where post.threadid = 51506; + ------ + ------------- + ------- + ------ + --------------- -+ ---------- + --------- + ------- ++ -------- + ------- + | 아이디 | select_type | 테이블 | 타입 | possible_keys | 열쇠 | key_len | 심판 | 행 | 추가 | + ------ + ------------- + ------- + ------ + --------------- -+ ---------- + --------- + ------- ++ -------- + ------- + | 1 | 단순 | 게시물 | 심판 | threadid | threadid | 4 | const | 124622 | | + ------ + ------------- + ------- + ------ + --------------- -+ ---------- + --------- + ------- ++ -------- + ------- + 1 행 세트 (0.00 초)
관련 인덱스가 없으면 전체 스캔이 인덱스 (!)를 사용하는 88 초에 비해 29 초만 걸린다는 것이 이상합니다.
완벽하게 맞춤화 된 하나의 색인만으로도 실제 사용에 비해 너무 느리게 완료하는 데 여전히 11 초가 걸립니다.
업데이트 2 :
정확히 동일한 하드웨어 구성과 정확히 동일한 데이터베이스 / 테이블로 다른 서버에서 MySQL (5.5.38-0ubuntu0.14.04.1 (Ubuntu))을 설정했습니다.
결과는 MyISAM Table과 거의 동일합니다.
. . | 5401593 | 0 | | 5401634 | 0 | + --------- + -------- + 62510 행 세트 (0.14 초)
그리고 이것은 InnoDB 테이블의 결과입니다
. . | 5397410 | 0 | | 5397883 | 0 | + --------- + -------- + 62510 행 세트 (1 분 17.63 초)
업데이트 3 : my.cnf의 내용
# MariaDB 데이터베이스 서버 구성 파일. # #이 파일을 다음 중 하나에 복사 할 수 있습니다. #- "/etc/mysql/my.cnf"는 전역 옵션을 설정합니다. #- "~ / .my.cnf"-사용자 별 옵션을 설정합니다. # # 프로그램이 지원하는 모든 긴 옵션을 사용할 수 있습니다. # --help로 프로그램을 실행하여 사용 가능한 옵션 목록을 얻으십시오. # --print-defaults는 실제로 이해하고 사용할 것을 확인합니다. # # 설명을 보려면 # http://dev.mysql.com/doc/mysql/en/server-system-variables.html # 이것은 모든 MySQL 클라이언트에게 전달됩니다 # 비밀번호는 틱 / 따옴표로 묶어야합니다. # "#"문자가 포함되어있는 경우 ... # 소켓 위치를 변경할 때 /etc/mysql/debian.cnf를 편집하십시오. [고객] 포트 = 3306 소켓 = /var/run/mysqld/mysqld.sock # 특정 프로그램에 대한 항목은 다음과 같습니다. # 다음 값은 최소 32M 램이 있다고 가정합니다. # 이것은 공식적으로 [safe_mysqld]로 알려졌습니다. 두 버전 모두 현재 구문 분석되었습니다. [mysqld_safe] 소켓 = /var/run/mysqld/mysqld.sock 좋은 = 0 [mysqld] # # * 기본 설정 # 사용자 = MySQL pid 파일 = /var/run/mysqld/mysqld.pid 소켓 = /var/run/mysqld/mysqld.sock 포트 = 3306 basedir = / usr datadir = / var / lib / mysql tmpdir = / tmp lc_messages_dir = / usr / share / mysql lc_messages = en_US 스킵 외부 잠금 # # 스킵 네트워킹 대신에 디폴트는 이제 리스닝 만합니다. # localhost 호환성이 높고 덜 안전합니다. 바인드 주소 = 127.0.0.1 # # * 미세 조정 # max_connections = 100 connect_timeout = 5 wait_timeout = 600 max_allowed_packet = 16M thread_cache_size = 128 sort_buffer_size = 4M bulk_insert_buffer_size = 16M tmp_table_size = 32M max_heap_table_size = 32M # # * MyISAM # # 이것은 시작 스크립트를 대체하고 필요한 경우 MyISAM 테이블을 확인합니다 # 처음 만졌을 때. 오류가 발생하면 복사하여 수리하십시오. myisam_recover = 백업 key_buffer_size = 128M # open-files-limit = 2000 table_open_cache = 400 myisam_sort_buffer_size = 512M concurrent_insert = 2 read_buffer_size = 2M read_rnd_buffer_size = 1M # # * 쿼리 캐시 구성 # # 작은 결과 집합 만 캐시하므로 쿼리 캐시에 더 적합 할 수 있습니다. query_cache_limit = 128K query_cache_size = 64M 쓰기 집약적 인 설정의 경우 # DEMAND 또는 OFF로 설정 #query_cache_type = DEMAND # # * 로깅 및 복제 # # 두 위치는 cronjob에 의해 회전됩니다. #이 로그 유형은 성능을 저하시키는 요소입니다. # 5.1부터 런타임에 로그를 활성화 할 수 있습니다! #general_log_file = /var/log/mysql/mysql.log #general_log = 1 # # /etc/mysql/conf.d/mysqld_safe_syslog.cnf로 인해 오류 로그가 syslog로 이동합니다. # # 우리는 네트워크 오류에 대해 알고 싶습니다 log_warnings = 2 # # 느린 쿼리 로그를 활성화하여 특히 긴 시간의 쿼리를 봅니다. #slow_query_log [= {0 | 1}] slow_query_log_file = /var/log/mysql/mariadb-slow.log long_query_time = 10 #log_slow_rate_limit = 1000 log_slow_verbosity = query_plan # log-queries-not-using-indexes #log_slow_admin_statements # # 다음은 백업 로그를 쉽게 재생하거나 복제하기 위해 사용할 수 있습니다. # 참고 : 복제 슬레이브를 설정하는 경우 README를 참조하십시오. # 다른 설정을 변경해야 할 수도 있습니다. # server-id = 1 #report_host = master1 #auto_increment_increment = 2 #auto_increment_offset = 1 log_bin = / var / log / mysql / mariadb-bin log_bin_index = /var/log/mysql/mariadb-bin.index # 성능을위한 팹은 아니지만 더 안전합니다. #sync_binlog = 1 expire_logs_days = 10 max_binlog_size = 100M 노예 # #relay_log = / var / log / mysql / relay-bin #relay_log_index = /var/log/mysql/relay-bin.index #relay_log_info_file = /var/log/mysql/relay-bin.info #log_slave_updates #read_only # # 애플리케이션이이를 지원하는 경우이 엄격한 sql_mode는 일부를 방지합니다. 잘못된 날짜 삽입 등의 실수 #sql_mode = NO_ENGINE_SUBSTITUTION, TRADITIONAL # # * InnoDB # # InnoDB는 기본적으로 / var / lib / mysql /에 10MB 데이터 파일로 활성화되어 있습니다. # 더 많은 InnoDB 관련 옵션에 대해서는 매뉴얼을 읽으십시오. 많이있다! default_storage_engine = InnoDB # 로그 파일 크기 만 변경할 수 없으며 특별한 절차가 필요합니다 #innodb_log_file_size = 50M innodb_buffer_pool_size = 20G innodb_log_buffer_size = 8M innodb_file_per_table = 1 innodb_open_files = 400 innodb_io_capacity = 400 innodb_flush_method = O_DIRECT # # * 보안 기능 # # chroot를 원하면 매뉴얼도 읽으십시오! # chroot = / var / lib / mysql / # # SSL 인증서를 생성하려면 OpenSSL GUI "tinyca"를 권장합니다. # # ssl-ca = / etc / mysql / cacert.pem # ssl-cert = / etc / mysql / server-cert.pem # ssl-key = / etc / mysql / server-key.pem [mysqldump] 빨리 인용 이름 max_allowed_packet = 16M [mysql] # no-auto-rehash # mysql의 빠른 시작이지만 탭 완성은 없습니다 [isamchk] key_buffer = 16M # # * 중요 :이 파일의 설정을 무시할 수있는 추가 설정! # 파일은 '.cnf'로 끝나야합니다. 그렇지 않으면 무시됩니다. # ! includedir /etc/mysql/conf.d/
그리고 inno 변수의 내용 :
MariaDB [(없음)]> 'inno %'와 같은 변수 표시; + ------------------------------------------- + ----- ------------------- + | Variable_name | 가치 | + ------------------------------------------- + ----- ------------------- + | innodb_adaptive_flushing | ON | | innodb_adaptive_flushing_lwm | 10 | | innodb_adaptive_hash_index | ON | | innodb_adaptive_hash_index_partitions | 1 | | innodb_adaptive_max_sleep_delay | 150000 | | innodb_additional_mem_pool_size | 8388608 | | 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_populate | OFF | | innodb_buffer_pool_size | 21474836480 | | innodb_change_buffer_max_size | 25 | | innodb_change_buffering | 모두 | | innodb_checksum_algorithm | innodb | | innodb_checksums | ON | | innodb_cleaner_lsn_age_factor | high_checkpoint | | 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_corrupt_table_action | 주장 | | innodb_data_file_path | ibdata1 : 12M : 자동 확장 | | innodb_data_home_dir | | | innodb_disable_sort_file_cache | OFF | | innodb_doublewrite | ON | | innodb_empty_free_list_algorithm | 백 오프 | | innodb_fake_changes | OFF | | innodb_fast_shutdown | 1 | | innodb_file_format | 영양 | | innodb_file_format_check | ON | | innodb_file_format_max | 영양 | | innodb_file_per_table | ON | | innodb_flush_log_at_timeout | 1 | | innodb_flush_log_at_trx_commit | 1 | | innodb_flush_method | O_DIRECT | | innodb_flush_neighbors | 1 | | innodb_flushing_avg_loops | 30 | | innodb_force_load_corrupted | OFF | | innodb_force_recovery | 0 | | innodb_foreground_preflush | exponential_backoff | | 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 | 400 | | innodb_io_capacity_max | 2000 | | innodb_kill_idle_transaction | 0 | | innodb_large_prefix | OFF | | innodb_lock_wait_timeout | 50 | | innodb_locking_fake_changes | ON | | innodb_locks_unsafe_for_binlog | OFF | | innodb_log_arch_dir | ./ | | innodb_log_arch_expire_sec | 0 | | innodb_log_archive | OFF | | innodb_log_block_size | 512 | | innodb_log_buffer_size | 8388608 | | innodb_log_checksum_algorithm | innodb | | innodb_log_compressed_pages | ON | | innodb_log_file_size | 50331648 | | innodb_log_files_in_group | 2 | | innodb_log_group_home_dir | ./ | | innodb_lru_scan_depth | 1024 | | innodb_max_bitmap_file_size | 104857600 | | innodb_max_changed_pages | 1000000 | | 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 | 400 | | 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 | 4 | | innodb_read_only | OFF | | innodb_replication_delay | 0 | | innodb_rollback_on_timeout | OFF | | innodb_rollback_segments | 128 | | innodb_sched_priority_cleaner | 19 | | innodb_show_locks_held | 10 | | innodb_show_verbose_locks | 0 | | 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 | 0 | | innodb_thread_sleep_delay | 10000 | | innodb_track_changed_pages | OFF | | innodb_undo_directory | . | | innodb_undo_logs | 128 | | innodb_undo_tablespaces | 0 | | innodb_use_atomic_writes | OFF | | innodb_use_fallocate | OFF | | innodb_use_global_flush_log_at_trx_commit | ON | | innodb_use_native_aio | ON | | innodb_use_stacktrace | OFF | | innodb_use_sys_malloc | ON | | innodb_version | 5.6.17-65.0 | | innodb_write_io_threads | 4 | + ------------------------------------------- + ----- ------------------- + 143 행 세트 (0.02 초)
기계의 코어 수는 8입니다.
Intel(R) Xeon(R) CPU E3-1246 v3 @ 3.50GHz
현재 /proc/cpuinfo
마지막 참고 사항 : RolandoMYSQLDBA가 제안한 인덱스로 쿼리를 실행하면 쿼리마다 약 11-20 초가 걸렸습니다. threadid에 대한 첫 번째 쿼리가 1 초 이내에 반환되는 것이 중요하다는 것을 지적하고 싶습니다. 이 스레드.