MySQL viết chậm


8

Việc chèn vào bảng sau mất tới 70 giây để hoàn thành:

CREATE TABLE IF NOT EXISTS `productsCategories` (
  `categoriesId` int(11) NOT NULL,
  `productsId` int(11) NOT NULL,
  PRIMARY KEY (`categoriesId`,`productsId`),
  KEY `categoriesId` (`categoriesId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Có khoảng 100.000 hàng trong bảng và nó đang chiếm 7 MB trên đĩa.

Có một số cài đặt trong MySQL có thể cải thiện hiệu suất ghi?

my.cnfTập tin của tôi như sau:

log-slow-queries="/var/log/mysql/slow-query.log"
long_query_time=1 
log-queries-not-using-indexes

innodb_buffer_pool_size=4G
innodb_log_buffer_size=4M
innodb_flush_log_at_trx_commit=2
innodb_thread_concurrency=8
innodb_flush_method=O_DIRECT

query_cache_size = 6G
key_buffer_size = 284M
query_cache_limit = 1024M
thread_cache_size = 128
table_cache = 12800

sort_buffer_size=2M
read_rnd_buffer_size = 8M
myisam_sort_buffer_size = 64M

read_buffer_size=128K

open_files_limit               = 1000
table_definition_cache         = 1024
table_open_cache               = 6000

max_heap_table_size=512M
tmp_table_size=4096M

max_connections=1000

thread_concurrency = 24

Đây là thiết lập phần cứng:

  • Dell R710
  • RAID10
  • RAM 48G

Với phần cứng này, tôi sẽ không nghĩ vấn đề sẽ là một nút cổ chai phần cứng.


Bạn có thể cung cấp một số dữ liệu khách quan? Nhật ký, phương pháp kiểm tra / điểm chuẩn của bạn và kết quả, đó là điều gì?
womble

Những loại nhật ký bạn muốn xem? Điều duy nhất tôi thấy tại sao nó mất nhiều thời gian như vậy là trong de mtop . Tôi sẽ kiểm tra mọi thứ khi thay đổi bảng thành bảng myisam, giới hạn bộ nhớ cao hơn, luồng cao hơn.
Ronn0

Cài đặt tốt nhất để cải thiện mysql ... là chuyển sang postgres lol
Antony Gibbs

thread_concurrency = 24 không có hiệu lực ... bạn có thể kết xuất dòng đó
Antony Gibbs

Câu trả lời:


16

QUAN SÁT # 1

Điều đầu tiên khiến tôi chú ý là cấu trúc bảng

CREATE TABLE IF NOT EXISTS `productsCategories` (
  `categoriesId` int(11) NOT NULL,
  `productsId` int(11) NOT NULL,
  PRIMARY KEY (`categoriesId`,`productsId`),
  KEY `categoriesId` (`categoriesId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Xin lưu ý rằng categoriesIdchỉ mục và KHÓA CHÍNH bắt đầu với cùng một cột. Nó là một chỉ số dư thừa. Vì bảng này là InnoDB, nên categoriesIdchỉ mục là dự phòng vì một lý do khác: Tất cả các chỉ mục phụ chứa khóa vào gen_clust_index (còn gọi là Clustered Index; Xem gen_clust_index được sử dụng trong mysql là gì? )

Nếu bạn loại bỏ categoriesIdchỉ mục với

ALTER TABLE productsCategories DROP INDEX categoriesId;

điều này sẽ cải thiện đáng kể các INSERT vì không phải thực hiện thêm bảo trì chỉ mục phụ và cụm.

QUAN SÁT # 2

Nếu bạn đang thực hiện bất kỳ thao tác chèn số lượng lớn nào, bạn cần một bộ đệm chèn số lượng lớn .

Xin vui lòng xem bài viết trước đây của tôi về điều này:

QUAN SÁT # 3

Kích thước tệp nhật ký của bạn là quá nhỏ !!! Nó phải là 25% của Bộ đệm InnoDB, trong trường hợp của bạn là 1G. Xem bài đăng của tôi về cách thay đổi kích thước Tệp nhật ký InnoDB .

QUAN SÁT # 4

Xin vui lòng, không đặt innodb_thread_concurrency !!! Tôi đã học trực tiếp tại Percona Live NYC để rời khỏi thiết lập đó một mình . Nó bị tắt theo mặc định trong MySQL 5.5, Plugin MySQL 5.1 InnoDB và Percona Server 5.1+.

QUAN SÁT # 5

Bạn cần sử dụng innodb_file_per_table. Nếu điều này bị vô hiệu hóa, tôi biến việc bảo trì tập tin trên ibdata1 thành một cơn ác mộng. Vui lòng đọc bài viết của tôi về cách dọn dẹp InnoDB để thực hiện điều này .

QUAN SÁT # 6

Nếu bạn đang sử dụng MySQL 5.5 hoặc Percona Server, bạn phải đặt một số tùy chọn nhất định để khiến InnoDB sử dụng nhiều CPU / nhiều lõi. Xin vui lòng xem bài viết của tôi trên các cài đặt .

QUAN SÁT # 7

Bạn có innodb_log_buffer_size=4M. Mặc định là 8M. Điều đó sẽ gây ra gấp đôi số lần xả vào các bản ghi làm lại. Điều đó cũng sẽ chống lại innodb_flush_log_at_trx_commit=2thiết lập của bạn . Vui lòng đặt thành 32M. Ngoài ra, vui lòng xem Tài liệu MySQL trên innodb_log_buffer_size .

Trước những quan sát này, vui lòng thêm hoặc thay thế các cài đặt sau:

[mysqld]
innodb_thread_concurrency = 0
innodb_read_io_threads = 64
innodb_write_io_threads = 64
innodb_io_capacity = 5000
innodb_file_per_table
innodb_log_file_size=1G
innodb_log_buffer_size=1G
bulk_insert_buffer_size = 256M

Ồ cảm ơn nhé! Tôi đã in tất cả các điểm và làm việc với nó bây giờ và lưu nó vào não để giúp đỡ những người khác trong tương lai. Cảm ơn nhiều!
Ronn0

2
query_cache_sizelà rất lớn, quá. Mỗi lần chèn sẽ cần tới 6GB bộ nhớ cache để xóa.
Aaron Brown

@AaronBrown Tôi đồng ý. Tôi đã đọc trong cuốn sách MySQL hiệu suất cao rằng InnoDB thực hiện những điều tẻ nhạt với ID giao dịch trên bảng InnoDB trong bộ đệm truy vấn khiến nó không cần thiết, không đề cập đến chậm, để sử dụng bộ đệm truy vấn. Trong thực tế, MySQL 4.1 có bộ đệm truy vấn bị vô hiệu hóa cho InnoDB.
RolandoMySQLDBA

Tôi nghĩ bộ đệm truy vấn hoàn toàn tách biệt với công cụ lưu trữ. Về cơ bản, nó tuần tự hóa tất cả các hoạt động ghi bằng cách buộc mọi thứ phải trải qua và quét bộ đệm truy vấn để truy vấn không hợp lệ. Tôi chưa bao giờ tìm thấy một trường hợp sử dụng cho nó và nó luôn gây ra vấn đề.
Aaron Brown

thêm một điều nữa để thêm vào: query_cache_size = 6G <- điều này hoàn toàn và hoàn toàn vô lý. Bộ nhớ cache truy vấn thường bị vô hiệu hóa tốt hơn và chắc chắn không nên cho vay hơn 32M hoặc 64M. Chi phí hoạt động của việc duy trì bộ đệm truy vấn 6G chắc chắn sẽ ảnh hưởng đến hiệu năng.
Gavin Towey

0

Bạn nên kiểm tra innodb_log_file_size, cài đặt mặc định là 5M, khá thấp để ghi các thiết lập chuyên sâu. Cân nhắc đặt nó thành 100M. Bạn sẽ phải xóa các ib_logfile*tệp cũ để khởi động DB với cài đặt mới. Vui lòng không xóa các tệp nhật ký trong khi máy chủ DB đang chạy, bạn sẽ phải dừng nó trước. Có lẽ bạn nên sao lưu các tệp nhật ký cũ trước, không chỉ xóa chúng.

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.