InnoDB 100x의 단순 SELECT가 MyISAM보다 느린 이유는 무엇입니까?


33

꽤 성가신 문제가 있습니다. INNODB를 기본 데이터베이스 엔진으로 사용하고 중복을 위해 galera-cluster를 사용하기 위해 전자가 필요하므로 MyISAM을 포기하고 싶습니다.

newbb_post테이블을 새 테이블로 복사하고 (설명 다음에) newbb_innopostInnoDB로 변경했습니다. 테이블에는 현재 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 초 이내에 반환되는 것이 중요하다는 것을 지적하고 싶습니다. 이 스레드.


의견은 긴 토론을위한 것이 아닙니다. 이 대화는 채팅 으로 이동 되었습니다 .
폴 화이트는 GoFundMonica가

답변:


24

당신의 질문

SELECT post.postid, post.attach FROM newbb_innopost AS post WHERE post.threadid = 51506;

언뜻보기에 그 쿼리는 테이블의 1.1597 % (5390146에서 62510)에만 닿아 야합니다. threadid 51506의 키 분배가 주어지면 빨라야합니다.

현실 점검

어떤 버전의 MySQL (Oracle, Percona, MariaDB)을 사용하더라도 InnoDB 아키텍처라는 공통의 하나의 적과 싸울 수는 없습니다.

InnoDB 아키텍처

클러스터형 인덱스

각 threadid 항목에는 기본 키가 첨부되어 있습니다. 이는 인덱스에서 읽을 때 ClusteredIndex (내부적으로 gen_clust_index) 내에서 기본 키 조회를 수행해야 함을 의미합니다 . ClusteredIndex에서 각 InnoDB 페이지에는 데이터와 PRIMARY KEY 인덱스 정보가 모두 들어 있습니다. 자세한 내용은 내 게시물 MyISAM 및 InnoDB 를 참조하십시오.

중복 색인

일부 인덱스의 선행 열이 같기 때문에 테이블에 많은 혼란이 있습니다. MySQL과 InnoDB는 필요한 BTREE 노드에 도달하기 위해 인덱스 클러 터를 탐색해야합니다. 다음을 실행하여 혼란을 줄이십시오.

ALTER TABLE newbb_innopost
    DROP INDEX threadid,
    DROP INDEX threadid_2,
    DROP INDEX threadid_visible_dateline,
    ADD INDEX threadid_visible_dateline_index (`threadid`,`visible`,`dateline`,`userid`)
;

왜 이러한 인덱스를 제거합니까?

  • 처음 세 개의 인덱스는 threadid로 시작합니다
  • threadid_2threadid_visible_dateline같은 세 개의 열 시작
  • threadid_visible_dateline 기본 키이므로 내장되어 있으므로 postid가 필요하지 않습니다.

버퍼 캐싱

InnoDB 버퍼 풀은 데이터 및 인덱스 페이지를 캐시합니다. MyISAM은 인덱스 페이지 만 캐시합니다.

이 영역에서만 MyISAM은 시간 캐싱 데이터를 낭비하지 않습니다. 데이터를 캐시하도록 설계되지 않았기 때문입니다. InnoDB는 접촉하는 모든 데이터 페이지와 인덱스 페이지 (및 그 할머니)를 캐시합니다. InnoDB 버퍼 풀이 너무 작은 경우, 하나의 쿼리에서 페이지를 캐시하고 페이지를 무효화하며 페이지를 모두 제거 할 수 있습니다.

테이블 레이아웃

당신은 고려하여 행의 일부 공간을 면도 할 수 importthreadidimportpostid. 당신은 그것들을 BIGINT로 가지고 있습니다. 행당 ClusteredIndex에서 16 바이트를 차지합니다.

당신은 이것을 실행해야합니다

SELECT importthreadid,importpostid FROM newbb_innopost PROCEDURE ANALYSE();

이는 주어진 데이터 셋에 대해이 열이 어떤 데이터 유형이어야하는지 권장합니다.

결론

MyISAM은 특히 캐싱 분야에서 InnoDB보다 훨씬 덜 경쟁합니다.

RAM의 양 ( 32GB)과 MySQL의 버전 ( ) 을 공개했지만 Server version: 10.0.12-MariaDB-1~trusty-wsrep-log mariadb.org binary distribution, wsrep_25.10.r4002,이 퍼즐에는 아직 공개하지 않은 다른 부분이 있습니다.

  • InnoDB 설정
  • 코어 수
  • 의 다른 설정 my.cnf

이러한 것들을 질문에 추가 할 수 있다면 더 자세히 설명 할 수 있습니다.

업데이트 2014-08-28 11:27 EDT

스레딩을 늘려야합니다

innodb_read_io_threads = 64
innodb_write_io_threads = 16
innodb_log_buffer_size = 256M

쿼리 캐시를 비활성화하는 것을 고려할 것입니다 (최근의 게시물 인 query_cache_type이 기본적으로 MySQL 5.6에서 시작하는 이유는 무엇입니까? 참조 )

query_cache_size = 0

버퍼 풀을 유지합니다

innodb_buffer_pool_dump_at_shutdown=1
innodb_buffer_pool_load_at_startup=1

제거 스레드 늘리기 (여러 테이블에서 DML을 수행하는 경우)

innodb_purge_threads = 4

시도 해봐 !!!


순수한 속도 테스트에서 InnoDB가 느리다는 것을 알고 있습니다. MySQL 팀이 이러한 격차를 해소하기 위해 열심히 노력하고 있다는 것을 읽었습니다. 우리는 여전히 ~ 100 배 증가를 다루고 있습니다! 질문-이 속성에 대한 쿼리는 "직접"비 클러스터형 B- 트리 인덱스 (즉, PK 데이터가 포함되지 않은)와 함께 더 잘 제공 될 것입니까? 그렇다면 왜 이것이 구현되지 않았거나 구현되지 않았습니까? OP에 필요한 기능은 분명한 사용 사례가 아닙니다.
Vérace

해당 사진의 전체 크기 버전에 대한 링크를 추가 할 수 있습니까? 일부 부품은 읽기가 어렵습니다 :-)
watery

정보에 대한 @RolandMySQLDBA 감사합니다-InnoDB의 100x 속도 저하가 "정상"이라고 제안하지 않기를 바랍니다. 나는 2x 또는 3x로 살 수 있지만 100x는 너무 많습니다. 요청에 따라 누락 된 정보를 내 질문에 추가했습니다 :) 지금까지 설명해 주셔서 감사합니다! 기계의 코어 수는 8입니다.
jollyroger

2
: @watery 여기에 전체 크기 사진입니다 scribd.com/doc/31337494/XtraDB-InnoDB-internals-in-drawing
RolandoMySQLDBA

1
@RolandoMySQLDBA를 도와 주셔서 감사합니다. 불행히도 마지막 조정조차도 도움이되지 않았으며 InnoDB는 완료하는 데 약 11-20 초가 걸립니다. 모든 색인을 삭제하고 취재 색인을 작성하여 귀하의 답변에 따라 무언가를 시도했습니다. 그것은 많은 도움이되었습니다. 색인에 대한 설명 없이는이 솔루션을 찾지 못했습니다. 답변을 확인하고 내가 한 일을 설명하는 답변을 직접 작성하려고합니다.)
jollyroger

7

@RolandMySQLDBA는 질문에 대답하는 올바른 힌트를주었습니다. 문제는 쿼리에있는 것처럼 보이며 결과를 다시 제공하려면 각 필드를 읽어야합니다 (어떻게 데이터베이스에서).

을 제외한 모든 색인을 삭제 PRIMARY KEY하고이 새로운 색인을 삽입했습니다.

ALTER TABLE newbb_innopost ADD INDEX threadid_visible_dateline_index (threadid,visible,dateline,userid,attach,ipaddress);

링크 는 여기서 발생하는 일을 설명합니다 ( index 포함 ) : 이제 쿼리 postid,attach자체에서 쿼리 된 필드를 키 자체에서 추출 할 수 있습니다. 따라서 실제 데이터를 확인하고 하드 디스크에 대한 I / O를 사용하지 않아도됩니다.

모든 쿼리는 이제 0.00 초로 실행됩니다. : :)

도와 주셔서 감사합니다.

편집 : 실제 근본적인 문제는 해결되지 않고 방금이 기술로 우회했습니다. InnoDB는이 영역에서 약간의 수정이 필요합니다.


나는 같은 문제에 직면하고있다. myisma 쿼리는 0.01 초가 걸리고 innodb는 60 초가 걸리므로 제안을 시도하십시오.
AMB

@AMB-0.01은 쿼리 캐시와 같은 냄새가납니다. 으로 다시 시간을 정하십시오 SQL_NO_CACHE.
Rick James

0

쿼리와 테이블을 기반으로 시계열 테이블에서 데이터를 선택하는 것처럼 보입니다. 따라서 동시에 삽입하기 때문에 쿼리 시간이 느려질 수 있습니까?

이 두 가지가 사실이라면 ScaleDB를 대안으로 고려해 볼 수 있습니까? 당신은 여전히 ​​더 적합한 엔진 인 MariaDB에있을 것입니다.

http ://www.scaledb.com-홈페이지 http://www.scaledb.com/download-form.php- 당사 제품


2
메이저 에디션은 무료가 아님을 추가해야합니다.
ypercubeᵀᴹ

0

엔진 모두 쿼리를 훨씬 빠르게 실행합니다.

INDEX(threadid, attach, postid)

이는 "커버링 (covering)"인덱스이고 인덱스 BTree를 사용하여 거의 같은 방식으로 작동하기 때문입니다.

또한 "콜드 (cold)"서버의 어느 엔진에서도 이것이 불가능하다고 말합니다 .

62510 rows in set (0.13 sec)

SQL_NO_CACHE타이밍을 실행할 때마다 사용 하십시오. 쿼리 캐시가 결론을 오염시키지 않기를 바랍니다.

또 다른 빠른 접근 방식 (I / O 캐싱에 무관) :

사용 이노와의 변화 PRIMARY KEY (postid)

PRIMARY KEY(threadid, postid),
INDEX(postid)

그 이유는이 이에 등, 적은 I / O를 필요로하는 모든 관련 행이 인접 원인이 될 것입니다 INDEX(postid)유지하는 것입니다 AUTO_INCREMENT행복. 주의 사항 : 이것은 모든 보조 키를 혼란스럽게합니다. 일부는 더 빠르며, 일부는 느릴 것입니다.


0

@jollyroger에 직접 적용 할 수는 없지만 이미 올바른 설정을 가지고 있기 때문에 왜 myisam이 Innodb보다 느린 지에innodb_buffer_pool_size 설명 된대로 RAM의 70 %로 변경하여 크게 개선 되었습니다.

처음 MyISAM은 느리지 만 oke. 그런 다음 InnoDB이 질문에서 100 배 느린 것과 비슷한 상황을 악화시키고 설정을 변경 한 후 InnoDB10 배 빠릅니다 MyISAM.

내 기본 설정은 8MB로 거의 작았습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.