Tại sao các CHỌN đơn giản trên InnoDB chậm hơn 100 lần so với trên MyISAM?


33

Tôi có một vấn đề khá khó chịu. Tôi muốn sử dụng INNODB làm công cụ cơ sở dữ liệu chính của mình và từ bỏ MyISAM vì tôi cần cái trước để sử dụng cụm galera để dự phòng.

Tôi đã sao chép (mô tả sau) newbb_postbảng vào một bảng mới được gọi newbb_innopostvà thay đổi bảng đó thành InnoDB. Các bảng hiện đang giữ 5,390,146các mục mỗi.

Chạy các lựa chọn này trên cơ sở dữ liệu mới bắt đầu (vì vậy không có bộ nhớ đệm nào được tham gia vào thời điểm này!) Cơ sở dữ liệu mang lại các kết quả sau (bỏ qua đầu ra hoàn chỉnh, xin lưu ý rằng tôi thậm chí không yêu cầu cơ sở dữ liệu sắp xếp kết quả):

CHỌN post.postid, post.attach TỪ newbb_post NHƯ bài đăng WHERE post.threadid = 51506;

.
.
| 5401593 | 0 |
| 5401634 | 0 |
+ --------- + -------- +
62510 hàng trong bộ (0,13 giây)
CHỌN post.postid, post.attach TỪ newbb_innopost NHƯ bài đăng WHERE post.threadid = 51506;
.
.
| 5397410 | 0 |
| 5394883 | 0 |
+ --------- + -------- +
62510 hàng trong bộ (1 phút 22,19 giây)

0,13 giây đến 86,19 giây (!)

Tôi tự hỏi tại sao điều này đang xảy ra. Tôi đã đọc một số câu trả lời ở đây trên Stackexchange liên quan đến InnoDB và một số gợi ý tăng innodb_buffer_poolkích thước lên 80% RAM được cài đặt. Điều này sẽ không giải quyết được vấn đề, rằng truy vấn ban đầu tới một ID cụ thể sẽ mất ít nhất 50 lần và làm trì hoãn toàn bộ trình duyệt web, xếp hàng các kết nối và truy vấn cho cơ sở dữ liệu. Sau đó, bộ đệm / bộ đệm có thể khởi động, nhưng có hơn 100.000 luồng trong cơ sở dữ liệu này, do đó rất có thể bộ đệm sẽ không bao giờ giữ tất cả các truy vấn có liên quan được cung cấp.

Các truy vấn ở trên rất đơn giản (không tham gia) và tất cả các khóa được sử dụng:

GIẢI THÍCH CHỌN post.postid, post.attach TỪ newbb_innopost NHƯ bài đăng WHERE post.threadid = 51506;
+ ------ + ------------- + ------- + ------ + ------------- ---------------------------------- + ---------- + ---- ----- + ------- + -------- + ------- +
| id | chọn_type | bàn | loại | có thể_key | chìa khóa | key_len | tham khảo | hàng | Thêm |
+ ------ + ------------- + ------- + ------ + ------------- ---------------------------------- + ---------- + ---- ----- + ------- + -------- + ------- +
| 1 | ĐƠN GIẢN | bài viết | tham khảo | threadid, threadid_2, threadid_visible_dateline | luồng | 4 | const | 120144 | |
+ ------ + ------------- + ------- + ------ + ------------- ---------------------------------- + ---------- + ---- ----- + ------- + -------- + ------- +

Đây là Bảng MyISAM:

TẠO BẢNG `newbb_post` (
  `postid` int (10) không dấu KHÔNG NULL AUTO_INCREMENT,
  `threadid` int (10) không dấu KHÔNG NULL DEFAULT '0',
  `Parentid` int (10) không dấu KHÔNG NULL DEFAULT '0',
  `username` varchar (100) KHÔNG NULL DEFAULT '',
  `userid` int (10) không dấu KHÔNG NULL DEFAULT '0',
  `title` varchar (250) KHÔNG NULL DEFAULT '',
  `dateline` int (10) không dấu KHÔNG NULL DEFAULT '0',
  `pagetext` trung gian,
  `allowmilie` smallint (6) KHÔNG NULL DEFAULT '0',
  `showignature` smallint (6) KHÔNG NULL DEFAULT '0',
  `ipaddress` varchar (15) KHÔNG NULL DEFAULT '',
  `iconid` smallint (5) không dấu KHÔNG NULL DEFAULT '0',
  `thấy được 'smallint (6) KHÔNG NULL DEFAULT' 0 ',
  `Đính kèm` smallint (5) không dấu KHÔNG NULL DEFAULT '0',
  `infraction` smallint (5) unsign KHÔNG NULL DEFAULT '0',
  `reportthreadid` int (10) không dấu KHÔNG NULL DEFAULT '0',
  `importthreadid` bigint (20) KHÔNG NULL DEFAULT '0',
  `importpostid` bigint (20) KHÔNG NULL DEFAULT '0',
  `convert_2_utf8` int (11) KHÔNG NULL,
  `htmlstate` enum ('tắt', 'on', 'on_nl2br') KHÔNG NULL DEFAULT 'on_nl2br',
  KHÓA CHÍNH (`postid`),
  KEY `threadid` (` threadid`, `userid`),
  KEY `importpost_index` (` importpostid`),
  KEY `dateline` (` dateline`),
  KEY `threadid_2` (` threadid`, `thấy`,` dateline`),
  KEY `convert_2_utf8` (` convert_2_utf8`),
  KEY `threadid_visible_dateline` (` threadid`, `thấy`,` dateline`, `userid`,` postid`),
  KHÓA `ipaddress` (` ipaddress`),
  KEY `userid` (` userid`, `Parentid`),
  KEY `user_date` (` userid`, `dateline`)
) ĐỘNG CƠ = MyISAM AUTO_INCREMENT = 5402802 CHARFA DEFAULT = latin1

và đây là Bảng InnoDB (hoàn toàn giống nhau):

TẠO BẢNG `newbb_innopost` (
  `postid` int (10) không dấu KHÔNG NULL AUTO_INCREMENT,
  `threadid` int (10) không dấu KHÔNG NULL DEFAULT '0',
  `Parentid` int (10) không dấu KHÔNG NULL DEFAULT '0',
  `username` varchar (100) KHÔNG NULL DEFAULT '',
  `userid` int (10) không dấu KHÔNG NULL DEFAULT '0',
  `title` varchar (250) KHÔNG NULL DEFAULT '',
  `dateline` int (10) không dấu KHÔNG NULL DEFAULT '0',
  `pagetext` trung gian,
  `allowmilie` smallint (6) KHÔNG NULL DEFAULT '0',
  `showignature` smallint (6) KHÔNG NULL DEFAULT '0',
  `ipaddress` varchar (15) KHÔNG NULL DEFAULT '',
  `iconid` smallint (5) không dấu KHÔNG NULL DEFAULT '0',
  `thấy được 'smallint (6) KHÔNG NULL DEFAULT' 0 ',
  `Đính kèm` smallint (5) không dấu KHÔNG NULL DEFAULT '0',
  `infraction` smallint (5) unsign KHÔNG NULL DEFAULT '0',
  `reportthreadid` int (10) không dấu KHÔNG NULL DEFAULT '0',
  `importthreadid` bigint (20) KHÔNG NULL DEFAULT '0',
  `importpostid` bigint (20) KHÔNG NULL DEFAULT '0',
  `convert_2_utf8` int (11) KHÔNG NULL,
  `htmlstate` enum ('tắt', 'on', 'on_nl2br') KHÔNG NULL DEFAULT 'on_nl2br',
  KHÓA CHÍNH (`postid`),
  KEY `threadid` (` threadid`, `userid`),
  KEY `importpost_index` (` importpostid`),
  KEY `dateline` (` dateline`),
  KEY `threadid_2` (` threadid`, `thấy`,` dateline`),
  KEY `convert_2_utf8` (` convert_2_utf8`),
  KEY `threadid_visible_dateline` (` threadid`, `thấy`,` dateline`, `userid`,` postid`),
  KHÓA `ipaddress` (` ipaddress`),
  KEY `userid` (` userid`, `Parentid`),
  KEY `user_date` (` userid`, `dateline`)
) ĐỘNG CƠ = InnoDB AUTO_INCREMENT = 5402802 CHARFA DEFAULT = latin1

Máy chủ, với RAM 32 GB:

Phiên bản máy chủ: 10.0.12-MariaDB-1 ~ trusty-wsrep-log mariadb.org phân phối nhị phân, wsrep_25.10.r4002

Nếu bạn cần tất cả các cài đặt biến innodb_, tôi có thể đính kèm nó vào bài viết này.

Cập nhật:

Tôi đã bỏ TẤT CẢ các chỉ mục ngoài chỉ mục chính, sau đó kết quả trông như thế này:

.
.
| 5402697 | 0 |
| 5402759 | 0 |
+ --------- + -------- +
62510 hàng trong bộ (29,74 giây)
GIẢI THÍCH CHỌN post.postid, post.attach TỪ newbb_innopost NHƯ bài đăng WHERE post.threadid = 51506;
+ ------ + ------------- + ------- + ------ + ------------- - + ------ + --------- + ------ + --------- + ------------- +
| id | chọn_type | bàn | loại | có thể_key | chìa khóa | key_len | tham khảo | hàng | Thêm |
+ ------ + ------------- + ------- + ------ + ------------- - + ------ + --------- + ------ + --------- + ------------- +
| 1 | ĐƠN GIẢN | bài viết | TẤT CẢ | NULL | NULL | NULL | NULL | 5909836 | Sử dụng ở đâu |
+ ------ + ------------- + ------- + ------ + ------------- - + ------ + --------- + ------ + --------- + ------------- +
1 hàng trong bộ (0,00 giây)

Sau này, tôi chỉ thêm một chỉ mục trở lại hỗn hợp, threadid, kết quả như sau:

.
.
| 5402697 | 0 |
| 5402759 | 0 |
+ --------- + -------- +
62510 hàng trong bộ (11,58 giây)
GIẢI THÍCH CHỌN post.postid, post.attach TỪ newbb_innopost NHƯ bài đăng WHERE post.threadid = 51506;
+ ------ + ------------- + ------- + ------ + ------------- - + ---------- + --------- + ------- + -------- + ------- +
| id | chọn_type | bàn | loại | có thể_key | chìa khóa | key_len | tham khảo | hàng | Thêm |
+ ------ + ------------- + ------- + ------ + ------------- - + ---------- + --------- + ------- + -------- + ------- +
| 1 | ĐƠN GIẢN | bài viết | tham khảo | luồng | luồng | 4 | const | 124622 | |
+ ------ + ------------- + ------- + ------ + ------------- - + ---------- + --------- + ------- + -------- + ------- +
1 hàng trong bộ (0,00 giây)

Điều kỳ lạ là, không có bất kỳ chỉ mục liên quan nào, quá trình quét toàn bộ chỉ mất 29 giây so với 88 giây sử dụng chỉ mục (!).

Chỉ với một chỉ số được thiết kế hoàn hảo, nó vẫn mất 11 giây để hoàn thành - vẫn còn quá chậm đối với bất kỳ việc sử dụng trong thế giới thực.

Cập nhật 2:

Tôi thiết lập MySQL (5.5,38-0ubfox0.14.04.1 (Ubuntu)) trên một máy chủ khác có cùng cấu hình phần cứng và chính xác cùng một cơ sở dữ liệu / bảng.

Các kết quả gần giống nhau, đầu tiên là Bảng MyISAM:

.
.
| 5401593 | 0 |
| 5401634 | 0 |
+ --------- + -------- +
62510 hàng trong bộ (0,14 giây)

Và đây là kết quả của bảng InnoDB

.
.
| 5397410 | 0 |
| 5394883 | 0 |
+ --------- + -------- +
62510 hàng trong bộ (1 phút 17,63 giây)

CẬP NHẬT 3: nội dung của my.cnf

# Tập tin cấu hình máy chủ cơ sở dữ liệu MariaDB.
#
# Bạn có thể sao chép tệp này vào một trong:
# - "/etc/mysql/my.cnf" để đặt các tùy chọn toàn cầu,
# - "~ / .my.cnf" để đặt tùy chọn cụ thể cho người dùng.
# 
# Một có thể sử dụng tất cả các tùy chọn dài mà chương trình hỗ trợ.
# Chạy chương trình với --help để nhận danh sách các tùy chọn khả dụng và với
# --print-mặc định để xem cái nào thực sự sẽ hiểu và sử dụng.
#
# Để giải thích xem
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html

# Điều này sẽ được truyền cho tất cả các máy khách mysql
# Nó đã được báo cáo rằng mật khẩu nên được đính kèm với dấu tick / dấu ngoặc kép
# đặc biệt nếu chúng chứa ký tự "#" ...
# Hãy nhớ chỉnh sửa /etc/mysql/debian.cnf khi thay đổi vị trí ổ cắm.
[khách hàng]
cổng = 3306
ổ cắm = /var/run/mysqld/mysqld.sock

# Đây là mục cho một số chương trình cụ thể
# Các giá trị sau giả sử bạn có ít nhất 32M ram

# Điều này được chính thức gọi là [safe_mysqld]. Cả hai phiên bản hiện đang được phân tích cú pháp.
[mysqld_safe]
ổ cắm = /var/run/mysqld/mysqld.sock
tốt đẹp = 0

[mysqld]
#
# * Cài đặt cơ bản
#
người dùng = mysql
pid-file = /var/run/mysqld/mysqld.pid
ổ cắm = /var/run/mysqld/mysqld.sock
cổng = 3306
dựair = / usr
datadir = / var / lib / mysql
tmpdir = / tmp
lc_messages_dir = / usr / share / mysql
lc_messages = en_US
bỏ qua khóa ngoài
#
# Thay vì bỏ qua mạng, mặc định bây giờ chỉ nghe
# localhost tương thích hơn và không kém an toàn.
địa chỉ liên kết = 127.0.0.1
#
# * Tinh chỉnh
#
max_connections = 100
kết nối_timeout = 5
chờ_timeout = 600
max_allowed_packet = 16M
thread_cache_size = 128
sort_buffer_size = 4M
số lượng lớn_insert_buffer_size = 16M
tmp_table_size = 32M
max_heap_table_size = 32M
#
# * MyISAM
#
# Điều này thay thế tập lệnh khởi động và kiểm tra các bảng MyISAM nếu cần
# lần đầu tiên họ được chạm vào. Khi có lỗi, tạo bản sao và thử sửa chữa.
myisam_recover = BACKUP
key_buffer_size = 128M
# tệp mở-giới hạn = 2000
bảng_open_cache = 400
myisam_sort_buffer_size = 512M
đồng thời_insert = 2
read_buffer_size = 2M
read_rnd_buffer_size = 1M
#
# * Cấu hình bộ đệm truy vấn
#
# Chỉ bộ đệm kết quả nhỏ, vì vậy chúng tôi có thể phù hợp hơn trong bộ đệm truy vấn.
truy vấn_cache_limit = 128K
truy vấn_cache_size = 64M
# để biết thêm các thiết lập chuyên sâu, hãy đặt thành DEMAND hoặc OFF
#query_cache_type = NHU CẦU
#
# * Ghi nhật ký và nhân rộng
#
# Cả hai vị trí được quay bởi cronjob.
# Hãy lưu ý rằng loại nhật ký này là một kẻ giết người hiệu suất.
# Kể từ 5.1 bạn có thể kích hoạt nhật ký khi chạy!
#general_log_file = /var/log/mysql/mysql.log
#general_log = 1
#
# Lỗi ghi nhật ký vào syslog do /etc/mysql/conf.d/mysqld_safe_syslog.cnf.
#
# chúng tôi muốn biết về lỗi mạng và như vậy
log_warnings = 2
#
# Kích hoạt nhật ký truy vấn chậm để xem các truy vấn có thời lượng đặc biệt dài
#slow_query_log [= {0 | 1}]
Slow_query_log_file = /var/log/mysql/mariadb-slow.log
dài_query_time = 10
#log_slow_rate_limit = 1000
log_slow_verbosity = query_plan

# log-truy vấn-không sử dụng chỉ mục
#log_slow_admin_statements
#
# Sau đây có thể được sử dụng như dễ dàng để phát lại các bản ghi dự phòng hoặc để nhân rộng.
# lưu ý: nếu bạn đang thiết lập nô lệ sao chép, hãy xem README.Debian về
# cài đặt khác bạn có thể cần thay đổi.
# máy chủ-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
# không fab cho hiệu suất, nhưng an toàn hơn
#sync_binlog = 1
expire_logs_days = 10
max_binlog_size = 100M
# nô lệ
#relay_log = / var / log / mysql / rơle-bin
#relay_log_index = /var/log/mysql/relay-bin.index
#relay_log_info_file = /var/log/mysql/relay-bin.info
#log_slave_updates
#chỉ đọc
#
# Nếu các ứng dụng hỗ trợ nó, sql_mode chặt chẽ hơn này sẽ ngăn một số
# lỗi như chèn ngày không hợp lệ, v.v.
#sql_mode = NO_ENGINE_SUBSTITNING, TRUYỀN THỐNG
#
# * InnoDB
#
# InnoDB được bật theo mặc định với tệp dữ liệu 10 MB trong / var / lib / mysql /.
# Đọc hướng dẫn để biết thêm các tùy chọn liên quan đến InnoDB. Có nhiều!
default_st Storage_engine = InnoDB
# bạn không thể thay đổi kích thước tệp nhật ký, yêu cầu thủ tục đặc biệt
#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
#
# * Tính năng bảo mật
#
# Đọc hướng dẫn, quá, nếu bạn muốn chroot!
# chroot = / var / lib / mysql /
#
# Để tạo chứng chỉ SSL, tôi khuyên dùng OpenSSL GUI "tinyca".
#
# ssl-ca = / etc / mysql / cacert.pem
# ssl-cert = / etc / mysql / server-cert.pem
# ssl-key = / etc / mysql / server-key.pem



[mysqldump]
nhanh chóng
tên trích dẫn
max_allowed_packet = 16M

[mysql]
# no-auto-Rehash # khởi động nhanh hơn của mysql nhưng không hoàn thành tab

[isamchk]
key_buffer = 16M

#
# * QUAN TRỌNG: Các cài đặt bổ sung có thể ghi đè lên từ tệp này!
# Các tệp phải kết thúc bằng '.cnf', nếu không chúng sẽ bị bỏ qua.
#
! bao gồm /etc/mysql/conf.d/

Và nội dung của các biến inno:

MariaDB [(không có)]> HIỂN THỊ BIỂU TƯỢNG THÍCH 'inno%';
+ ------------------------------------------- + ----- ------------------- +
| Biến_ame | Giá trị |
+ ------------------------------------------- + ----- ------------------- +
| innodb_adaptive_flushing | TRÊN |
| innodb_adaptive_flushing_lwm | 10 |
| innodb_adaptive_hash_index | TRÊN |
| innodb_adaptive_hash_index_partitions | 1 |
| innodb_adaptive_max_s ngủ_delay | 150000 |
| innodb_additable_mem_pool_size | 8388608 |
| innodb_api_bk_commit_interval | 5 |
| innodb_api_disable_rowlock | TẮT |
| innodb_api_enable_binlog | TẮT |
| innodb_api_enable_mdl | TẮT |
| innodb_api_trx_level | 0 |
| innodb_autoextend_increment | 64 |
| innodb_autoinc_lock_mode | 1 |
| innodb_buffer_pool_dump_at_shutdown | TẮT |
| innodb_buffer_pool_dump_now | TẮT |
| innodb_buffer_pool_filename | ib_buffer_pool |
| innodb_buffer_pool_instances | 8 |
| innodb_buffer_pool_load_abort | TẮT |
| innodb_buffer_pool_load_at_startup | TẮT |
| innodb_buffer_pool_load_now | TẮT |
| innodb_buffer_pool_population | TẮT |
| innodb_buffer_pool_size | 21474836480 |
| innodb_change_buffer_max_size | 25 |
| innodb_change_buffering | tất cả |
| innodb_checksum_alacticm | nhà trọ |
| innodb_checksums | TRÊN |
| innodb_cleaner_lsn_age_factor | cao_checkpoint |
| innodb_cmp_per_index_enables | TẮT |
| innodb_commit_concurrency | 0 |
| innodb_compression_failure_thr Ngưỡng_pct | 5 |
| innodb_compression_level | 6 |
| innodb_compression_pad_pct_max | 50 |
| innodb_concurrency_tickets | 5000 |
| innodb_corrupt_table_action | khẳng định |
| innodb_data_file_path | ibdata1: 12M: tự động nhập |
| innodb_data_home_dir | |
| innodb_disable_sort_file_cache | TẮT |
| innodb_doublewrite | TRÊN |
| innodb_empty_free_list_alacticm | lùi lại |
| innodb_fake_changes | TẮT |
| innodb_fast_shutdown | 1 |
| innodb_file_format | Linh dương |
| innodb_file_format_check | TRÊN |
| innodb_file_format_max | Linh dương |
| innodb_file_per_table | TRÊN |
| innodb_flush_log_at_timeout | 1 |
| innodb_flush_log_at_trx_commit | 1 |
| innodb_flush_method | O_DIRECT |
| innodb_flush_neighbor | 1 |
| innodb_flushing_avg_loops | 30 |
| innodb_force_load_corrupted | TẮT |
| innodb_force_recovery | 0 |
| innodb_forground_preflush | exponential_backoff |
| innodb_ft_aux_table | |
| innodb_ft_cache_size | 8000000 |
| innodb_ft_enable_diag_print | TẮT |
| innodb_ft_enable_stopword | TRÊN |
| innodb_ft_max_token_size | 84 |
| innodb_ft_min_token_size | 3 |
| innodb_ft_num_word_optizes | 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 | TẮT |
| innodb_lock_wait_timeout | 50 |
| innodb_locking_fake_changes | TRÊN |
| innodb_locks_unsafe_for_binlog | TẮT |
| innodb_log_arch_dir | ./ |
| innodb_log_arch_Exire_sec | 0 |
| innodb_log_archive | TẮT |
| innodb_log_block_size | 512 |
| innodb_log_buffer_size | 8388608 |
| innodb_log_checksum_alacticm | nhà trọ |
| innodb_log_compression_pages | TRÊN |
| 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_denty_pages_pct | 75 |
| innodb_max_denty_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_optizes_fulltext_only | TẮT |
| innodb_page_size | 16384 |
| innodb_print_all_deadlocks | TẮT |
| innodb_purge_batch_size | 300 |
| innodb_purge_threads | 1 |
| innodb_random_read_ahead | TẮT |
| innodb_read_ahead_thr Ngưỡng | 56 |
| innodb_read_io_threads | 4 |
| innodb_read_only | TẮT |
| innodb numplication_delay | 0 |
| innodb_rollback_on_timeout | TẮT |
| innodb_rollback_segments | 128 |
| innodb_sched_p Warriority_cleaner | 19 |
| innodb_show_locks_ained | 10 |
| innodb_show_verbose_locks | 0 |
| innodb_sort_buffer_size | 1048576 |
| innodb_spin_wait_delay | 6 |
| innodb_stats_auto_recalc | TRÊN |
| innodb_stats_method | nulls_equal |
| innodb_stats_on_metadata | TẮT |
| innodb_stats_persistent | TRÊN |
| innodb_stats_persistent_sample_pages | 20 |
| innodb_stats_sample_pages | 8 |
| innodb_stats_transient_sample_pages | 8 |
| innodb_statusDefput | TẮT |
| innodb_statusDefput_locks | TẮT |
| innodb_strict_mode | TẮT |
| innodb_support_xa | TRÊN |
| innodb_sync_array_size | 1 |
| innodb_sync_spin_loops | 30 |
| innodb_table_locks | TRÊN |
| innodb_thread_concurrency | 0 |
| innodb_thread_s ngủ_delay | 10000 |
| innodb_track_changed_pages | TẮT |
| innodb_undo_directory | . |
| innodb_undo_logs | 128 |
| innodb_undo_tablespaces | 0 |
| innodb_use_atomic_writes | TẮT |
| innodb_use_fallocate | TẮT |
| innodb_use_global_flush_log_at_trx_commit | TRÊN |
| innodb_use_native_aio | TRÊN |
| innodb_use_stacktrace | TẮT |
| innodb_use_sys_malloc | TRÊN |
| innodb_version | 5.6.17-65.0 |
| innodb_write_io_threads | 4 |
+ ------------------------------------------- + ----- ------------------- +
143 hàng trong bộ (0,02 giây)

Số lượng lõi của máy là 8, đó là một

Intel(R) Xeon(R) CPU E3-1246 v3 @ 3.50GHz kể từ /proc/cpuinfo

Một lưu ý cuối cùng: Chạy các truy vấn với các chỉ mục được đề xuất bởi RolandoMYSQLDBA và các truy vấn mất khoảng 11-20 giây mỗi truy vấn. Tôi muốn chỉ ra rằng điều quan trọng đối với tôi (đây là bảng chính của bảng thông báo) rằng truy vấn đầu tiên về luồng được trả về trong chưa đầy một giây, vì có hơn 60.000 luồng và google-bot liên tục thu thập dữ liệu những chủ đề này.


Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
Paul White nói GoFundMonica

Câu trả lời:


24

SỐ LƯỢNG CỦA BẠN

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

Thoạt nhìn, truy vấn đó chỉ nên chạm 1,1597% (62510 trong số 5390146) của bảng. Cần nhanh chóng đưa ra phân phối chính của threadid 51506.

KIỂM TRA THỰC TẾ

Cho dù bạn sử dụng phiên bản MySQL nào (Oracle, Percona, MariaDB), không ai trong số họ có thể chiến đấu với một kẻ thù mà tất cả họ đều có chung: Kiến trúc InnoDB.

Kiến trúc InnoDB

CHỈ SỐ XÁC NHẬN

Xin lưu ý rằng mỗi mục nhập luồng có khóa chính được đính kèm. Điều này có nghĩa là khi bạn đọc từ chỉ mục, nó phải thực hiện tra cứu khóa chính trong Clustered Index (tên nội bộ là gen_clust_index) . Trong Clustered Index, mỗi trang InnoDB chứa cả dữ liệu và thông tin chỉ mục PRIMARY KEY. Xem bài đăng của tôi Best of MyISAM và InnoDB để biết thêm thông tin.

CHỈ SỐ GIẢM GIÁ

Bạn có rất nhiều lộn xộn trong bảng vì một số chỉ mục có cùng các cột hàng đầu. MySQL và InnoDB phải điều hướng qua sự lộn xộn chỉ mục để đến các nút BTREE cần thiết. Bạn nên giảm sự lộn xộn đó bằng cách chạy như sau:

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`)
;

Tại sao tước bỏ các chỉ số này?

  • Ba chỉ mục đầu tiên bắt đầu với threadid
  • threadid_2threadid_visible_dateline bắt đầu với ba cột giống nhau
  • threadid_visible_dateline không cần postid vì nó là PRIMary KEY và nó được nhúng

GẠCH BUFFER

Bộ đệm InnoDB lưu trữ dữ liệu và các trang chỉ mục. MyISAM chỉ lưu trữ các trang chỉ mục.

Chỉ trong khu vực này, MyISAM không lãng phí thời gian lưu trữ dữ liệu. Đó là bởi vì nó không được thiết kế để lưu trữ dữ liệu. InnoDB lưu trữ mọi trang dữ liệu và trang chỉ mục (và bà của nó) mà nó chạm vào. Nếu Nhóm bộ đệm InnoDB của bạn quá nhỏ, bạn có thể lưu các trang bộ đệm, vô hiệu hóa các trang và xóa tất cả các trang trong một truy vấn.

BẢNG SỐNG

Bạn có thể cạo một số không gian từ hàng bằng cách xem xét importthreadidimportpostid. Bạn có chúng là BIGINTs. Chúng chiếm 16 byte trong Clustered Index mỗi hàng.

Bạn nên chạy cái này

SELECT importthreadid,importpostid FROM newbb_innopost PROCEDURE ANALYSE();

Điều này sẽ đề xuất những loại dữ liệu mà các cột này nên có cho tập dữ liệu đã cho.

PHẦN KẾT LUẬN

MyISAM có rất ít tranh cãi hơn so với InnoDB, đặc biệt là trong lĩnh vực lưu trữ.

Mặc dù bạn đã tiết lộ dung lượng RAM ( 32GB) và phiên bản MySQL ( Server version: 10.0.12-MariaDB-1~trusty-wsrep-log mariadb.org binary distribution, wsrep_25.10.r4002), nhưng vẫn còn những mảnh khác cho câu đố này mà bạn chưa tiết lộ

  • Cài đặt InnoDB
  • Số lượng lõi
  • Các cài đặt khác từ my.cnf

Nếu bạn có thể thêm những điều này vào câu hỏi, tôi có thể giải thích thêm.

CẬP NHẬT 2014-08-28 11:27 EDT

Bạn nên tăng luồng

innodb_read_io_threads = 64
innodb_write_io_threads = 16
innodb_log_buffer_size = 256M

Tôi sẽ xem xét việc vô hiệu hóa bộ đệm truy vấn (Xem bài đăng gần đây của tôi Tại sao query_cache_type bị tắt theo mặc định bắt đầu từ MySQL 5.6? )

query_cache_size = 0

Tôi sẽ bảo vệ vùng đệm

innodb_buffer_pool_dump_at_shutdown=1
innodb_buffer_pool_load_at_startup=1

Tăng các luồng thanh lọc (nếu bạn thực hiện DML trên nhiều bảng)

innodb_purge_threads = 4

HÃY THỬ MỘT LẦN !!!


Tôi biết rằng InnoDB có nghĩa là chậm hơn trong một bài kiểm tra tốc độ thuần túy, nhưng đến mức này? Tôi đã đọc rằng nhóm MySQL đã làm việc chăm chỉ để thu hẹp khoảng cách này. Chúng tôi vẫn đang xử lý tăng gấp 100 lần! Câu hỏi - bạn có nói rằng các truy vấn có tính chất này sẽ được phục vụ tốt hơn với chỉ mục cây B không trực tiếp "trực tiếp" (nghĩa là không bao gồm dữ liệu PK)? Nếu vậy, tại sao điều này chưa / chưa được thực hiện? Các chức năng mà OP yêu cầu chắc chắn không phải là trường hợp sử dụng cận biên.
Vérace

Bạn có thể thêm một liên kết đến phiên bản kích thước đầy đủ của hình ảnh đó? Một số phần khó đọc :-)
chảy nước

@RolandMySQLDBA cảm ơn về thông tin - Tôi hy vọng bạn không cho rằng việc chậm 100 lần là "bình thường" đối với InnoDB ... Tôi có thể sống với 2x hoặc 3x, nhưng 100x đơn giản là quá nhiều. Theo yêu cầu, tôi đã thêm thông tin còn thiếu vào câu hỏi của mình :) Cảm ơn bạn đã giải thích cho đến nay! Số lõi của máy là 8.
jollyroger

2
@watery Đây là hình ảnh kích thước đầy đủ: scribd.com/doc/31337494/XtraDB-InnoDB-iternals-in-drawing
RolandoMyQueryDBA

1
Cảm ơn rất nhiều vì sự giúp đỡ của bạn @RolandoMySQLDBA, thật không may, ngay cả những điều chỉnh cuối cùng cũng không giúp được gì và InnoDB mất khoảng 11-20 giây để hoàn thành. Tôi đã thử một cái gì đó dựa trên câu trả lời của bạn - bỏ tất cả các chỉ mục và tạo ra một chỉ mục bao trùm. Điều đó đã giúp rất nhiều. Nếu không có lời giải thích của bạn về các chỉ mục, tôi sẽ không tìm thấy giải pháp này. Đi để kiểm tra câu trả lời của bạn và tự viết một câu trả lời giải thích những gì tôi đã làm :)
jollyroger

7

@RolandMySQLDBA đã đưa ra gợi ý đúng để trả lời câu hỏi. Vấn đề dường như nằm ở truy vấn và để các kết quả được trả lại, mỗi trường đó phải được đọc (bằng cách nào đó từ cơ sở dữ liệu).

Tôi đã bỏ tất cả các chỉ mục nhưng PRIMARY KEY, và chèn chỉ mục mới này:

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

Liên kết này giải thích những gì xảy ra ở đây ( bao gồm chỉ mục ): Các trường được truy vấn của truy vấn hiện postid,attachcó thể được trích xuất từ ​​chính khóa. Điều đó giúp tiết kiệm việc kiểm tra dữ liệu thực và sử dụng I / O vào đĩa cứng.

Tất cả các truy vấn hiện chạy với 0,00 giây .. :)

Cảm ơn rất nhiều tất cả sự giúp đỡ của bạn.

Chỉnh sửa : Vấn đề cơ bản thực tế không được giải quyết, tôi chỉ phá vỡ nó bằng kỹ thuật này. InnoDB cần một số sửa chữa nghiêm trọng trong lĩnh vực này.


tôi đang phải đối mặt với vấn đề tương tự. truy vấn myisma mất 0,01 giây trong khi innodb mất 60 giây, sẽ thử các đề xuất của bạn.
AMB

@AMB - 0,01s có mùi giống như bộ đệm Truy vấn; thời gian nó lại với SQL_NO_CACHE.
Rick James

0

Dựa trên cả truy vấn và bảng của bạn, có vẻ như bạn đang chọn dữ liệu từ bảng chuỗi thời gian. Như vậy, có thể là thời gian truy vấn chậm vì bạn đang chèn đồng thời?

Nếu hai điều đó là đúng, tôi có thể đề nghị xem xét ScaleDB như một giải pháp thay thế không? Bạn vẫn sẽ ở trên MariaDB, chỉ (có thể) một công cụ phù hợp hơn.

http://www.scaledb.com - Trang chủ http://www.scaledb.com/doad-form.php - sản phẩm của chúng tôi


2
Bạn nên thêm rằng phiên bản chính không miễn phí.
ypercubeᵀᴹ

0

Cả hai công cụ sẽ chạy truy vấn nhanh hơn nhiều với

INDEX(threadid, attach, postid)

Điều này là do nó sẽ là một chỉ mục "bao phủ" và sẽ hoạt động gần như giống nhau (sử dụng chỉ số BTree).

Ngoài ra, tôi sẽ nói rằng điều này là không thể đối với cả hai động cơ trên máy chủ "lạnh":

62510 rows in set (0.13 sec)

Vui lòng sử dụng SQL_NO_CACHEbất cứ khi nào chạy thời gian - chúng tôi không muốn bộ đệm Truy vấn gây ô nhiễm kết luận.

Một cách tiếp cận nhanh khác (vô tận bộ nhớ đệm I / O):

Sử dụng InnoDB và thay đổi từ PRIMARY KEY (postid)thành

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

Lý do là điều này sẽ làm cho tất cả các hàng có liên quan liền kề nhau, do đó yêu cầu ít I / O hơn, v.v ... INDEX(postid)Đó là để giữ AUTO_INCREMENThạnh phúc. Hãy cẩn thận: Điều này gây rối với tất cả các phím phụ - một số sẽ nhanh hơn, một số sẽ chậm hơn.


0

Mặc dù không thể áp dụng trực tiếp cho @jollyroger vì anh ta đã có cài đặt chính xác, nhưng tôi đã có một cải tiến lớn khi thay đổi innodb_buffer_pool_size70% RAM của mình như được giải thích trong Tại sao myisam chậm hơn Innodb

Đầu tiên MyISAMlà chậm, nhưng oke. Sau đó, InnoDBlàm cho mọi thứ trở nên tồi tệ, tương tự như chậm hơn 100 lần trong câu hỏi này và sau khi thay đổi cài đặt InnoDBđã nhanh hơn gấp 10 lần MyISAM.

Cài đặt mặc định của tôi là 8 MB, rất ít.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.