Làm cách nào để sử dụng độ trễ chèn với công cụ InnoDB và sử dụng ít kết nối hơn cho các câu lệnh chèn?


10

Tôi đang làm việc trên một ứng dụng bao gồm rất nhiều cơ sở dữ liệu ghi, khoảng ~ 70% chèn và 30% đọc. Tỷ lệ này cũng sẽ bao gồm các bản cập nhật mà tôi cho là một lần đọc và một lần viết. Thông qua các câu lệnh chèn, nhiều khách hàng chèn dữ liệu vào cơ sở dữ liệu thông qua câu lệnh chèn bên dưới:

$mysqli->prepare("INSERT INTO `track` (user, uniq_name, ad_name, ad_delay_time ) values (?, ?, ?, ?)");

Câu hỏi là tôi nên sử dụng insert_delay hay sử dụng cơ chế mysqli_multi_query vì câu lệnh insert sử dụng cpu ~ 100% trên máy chủ. Tôi đang sử dụng công cụ InnoDB trên cơ sở dữ liệu của mình để không thể chèn chậm. Chèn trên máy chủ là ~ 36k / giờ và đọc 99,89%, tôi cũng đang sử dụng câu lệnh chọn ở đó lấy dữ liệu bảy lần trong một truy vấn duy nhất , truy vấn này mất 150 giây trên máy chủ để thực thi. Tôi có thể sử dụng loại kỹ thuật hoặc cơ chế nào cho nhiệm vụ này? Bộ nhớ máy chủ của tôi là 2 gb, tôi có nên mở rộng bộ nhớ không?. Có một cái nhìn về vấn đề này, bất kỳ đề nghị sẽ được biết ơn với tôi.

Cấu trúc của bảng:

+-----------------+--------------+------+-----+-------------------+----------------+
| Field           | Type         | Null | Key | Default           | Extra          |
+-----------------+--------------+------+-----+-------------------+----------------+
| id              | int(11)      | NO   | PRI | NULL              | auto_increment |
| user            | varchar(100) | NO   |     | NULL              |                |
| uniq_name       | varchar(200) | NO   |     | NULL              |                |
| ad_name         | varchar(200) | NO   |     | NULL              |                |
| ad_delay_time   | int(11)      | NO   |     | NULL              |                |
| track_time      | timestamp    | NO   | MUL | CURRENT_TIMESTAMP |                |
+-----------------+--------------+------+-----+-------------------+----------------+

Cơ sở dữ liệu của tôi hiện trạng, nó hiển thị 41k phần chèn (ghi), rất chậm cho cơ sở dữ liệu của tôi.

tình trạng cơ sở dữ liệu


Bạn có thể cung cấp định nghĩa của bảng? (tất cả các cột, kiểu dữ liệu và chỉ mục)
ypercubeᵀᴹ

Bạn có thể đưa ra một đoạn ngắn của bạn SHOW FULL PROCESSLISTkhi nó đang sử dụng cpu 100% không? Có bao nhiêu kết nối bạn cho phép so với bao nhiêu kết nối được thực hiện trong thời gian này?
Derek Downey

Hãy chạy hai truy vấn sau đây: SHOW GLOBAL VARIABLES LIKE 'innodb%';SELECT VERSION();và hiển thị đầu ra của họ.
RolandoMySQLDBA

Vui lòng cung cấp số lượng chèn mỗi giây bạn đang thực hiện.
dabest1

Mã của bạn rất dễ bị tiêm SQL. Sử dụng các câu lệnh được chuẩn bị và các giá trị tham số.
Aaron Brown

Câu trả lời:


11

Vì bạn có nhiều bài viết hơn nên đọc, tôi muốn giới thiệu những điều sau đây

Điều chỉnh chính xác của InnoDB sẽ là chìa khóa

Vùng đệm (Được định cỡ bởi innodb_buffer_pool_size )

InnoDB không hỗ trợ CHẬM TRÌ HOÃN , nên sử dụng Nhóm đệm InnoDB lớn là điều gần gũi nhất mà bạn có thể nhận được để XÁC NHẬN. Tất cả DML (CHERTN, CẬP NHẬT và XÓA) sẽ được lưu trong bộ đệm của InnoDB. Thông tin giao dịch cho các Writes được ghi ngay vào Nhật ký Redo (ib_logfile0, ib_logfile1). Việc ghi được đăng trong Bộ đệm được định kỳ xóa từ bộ nhớ sang đĩa thông qua ibdata1 (ChènBuffer cho Chỉ mục phụ, Bộ đệm ghi đôi). Vùng đệm càng lớn, số lượng INSERT càng lớn có thể được lưu trữ. Trong một hệ thống có RAM 8GB trở lên, hãy sử dụng 75-80% RAM làm innodb_buffer_pool_size. Trong một hệ thống có rất ít RAM, 25% (để chứa HĐH).

CAVEAT: Bạn có thể đặt innodb_doublewrite thành 0 để tăng tốc độ ghi thậm chí nhiều hơn, nhưng có nguy cơ toàn vẹn dữ liệu. Bạn cũng có thể tăng tốc mọi thứ bằng cách đặt innodb_flush_method thành O_DIRECT để ngăn bộ đệm InnoDB vào HĐH.

Làm lại Nhật ký (Được định cỡ bởi innodb_log_file_size )

Theo mặc định, nhật ký làm lại được đặt tên là ib_logfile0 và ib_logfile1 và sẽ là 5 MB mỗi bản ghi. Kích thước phải là 25% của innodb_buffer_pool_size. Nếu các bản ghi làm lại đã tồn tại, hãy thêm cài đặt mới trong my.cnf, tắt mysql, xóa chúng và khởi động lại mysql .

Bộ đệm nhật ký (Được định cỡ bởi innodb_log_buffer_size )

Bộ đệm nhật ký giữ các thay đổi trong RAM trước khi đưa chúng vào nhật ký làm lại. Mặc định là 8M. Bộ đệm nhật ký càng lớn, đĩa I / O càng ít. Hãy cẩn thận với các giao dịch rất lớn, vì điều này có thể làm chậm CAM KẾT bằng mili giây.

Truy cập nhiều CPU

MySQL 5.5 và Plugin MySQL 5.1 InnoDB có các cài đặt để InnoDB Storage Engine truy cập nhiều CPU. Dưới đây là các tùy chọn bạn cần đặt:

  • innodb_thread_concurrency đặt giới hạn trên cho số lượng luồng đồng thời mà InnoDB có thể giữ mở. Thông thường nên đặt cho điều này là (2 X Số lượng CPU) + Số lượng đĩa. Năm ngoái, tôi đã học được từ Hội nghị Percona NYC rằng bạn nên đặt giá trị này thành 0 để cảnh báo cho Công cụ lưu trữ InnoDB để tìm số luồng tốt nhất cho môi trường mà nó đang chạy.
  • innodb_concurrency_tickets đặt số lượng chủ đề có thể bỏ qua việc kiểm tra đồng thời mà không bị trừng phạt. Sau khi đạt đến giới hạn đó, kiểm tra đồng thời luồng trở lại định mức.
  • innodb_commit_concurrency đặt số lượng giao dịch đồng thời có thể được cam kết. Vì mặc định là 0, không thiết lập điều này cho phép bất kỳ số lượng giao dịch nào được cam kết đồng thời.
  • innodb_thread_s ngủ_delay đặt số mili giây mà một chuỗi InnoDB có thể không hoạt động trước khi nhập lại hàng đợi InnoDB. Mặc định là 10000 (10 giây).
  • innodb_read_io_threads (đặt giá trị này thành 3000) và innodb_write_io_threads (đặt giá trị này thành 7000) (cả hai từ MySQL 5.1,38) phân bổ số lượng luồng được chỉ định để đọc và ghi. Mặc định là 4 và tối đa là 64. Đặt các giá trị này thành 64. Ngoài ra, hãy đặt innodb_io_capacity thành 10000.

Nâng cấp lên MySQL 5.5

Nếu bạn có MySQL 5.0, hãy nâng cấp lên MySQL 5.5. Nếu bạn có MySQL 5.1.37 hoặc trước đó, hãy nâng cấp lên MySQL 5.5. Nếu bạn có MySQL 5.1,38 trở lên và muốn ở lại MySQL 5.1, hãy cài đặt Plugin InnoDB. Bằng cách đó, bạn có thể tận dụng tất cả các CPU cho InnoDB.


Bộ nhớ máy chủ của tôi là 2GB, vì vậy theo bộ nhớ, tôi đặt nhóm bộ đệm innodb thành 500M và tệp nhật ký 25% cho nhóm, cũng đặt bộ đệm nhật ký thành 64M. Nhưng máy chủ vẫn bận rộn. Có nên nâng cấp bộ nhớ? Ngoài ra máy chủ của tôi là trên Ubuntu 32 bit, vì vậy tối đa tôi có thể đặt bộ nhớ thành 4 GB.
Shashank

Nếu máy chủ chỉ dành cho MySQL (không có apache, không có PHP), thì innodb_buffer_pool_size có thể tăng 75% của 2GB, tức là 1536M. Nếu bạn nâng cấp lên 4GB, innodb_buffer_pool_size có thể là 3G. Các tệp nhật ký phải là 25% của vùng đệm như bạn đã nêu.
RolandoMySQLDBA

Máy chủ đang chạy apache2, mysql và php, tôi có nên nâng cấp bộ nhớ trong tình huống này hay có giải pháp tối ưu nào ngoại trừ nhóm bộ đệm innodb không?
Shashank

Anh chàng này không đồng ý với bạn: percona.com/blog/2008/11/21/ Khăn khó tranh luận với Percona.
Zenexer

Rolando - đề nghị bạn thêm vào câu trả lời với các bản cập nhật cho 5.6 và 5.7. Mặc định đã thay đổi; các cài đặt khác có sẵn; vv Có thể bao gồm Percona và MariaDB và 8.0 mẹo.
Rick James

2

INT (2) vẫn sử dụng 4 byte - có lẽ ý bạn là TINYINT KHÔNG ĐƯỢC KÝ?

Có bao nhiêu giá trị khác nhau trong setno? Nếu nó nhỏ, KEY (setno) sẽ không bao giờ được sử dụng. XÁC NHẬN phải cập nhật chỉ số đó; loại bỏ các phím sẽ tăng tốc một số.

CHAR (10) - flagLuôn dài 10 ký tự? Và trong utf8? Có lẽ bạn có thể sử dụng cờ VARCHAR (10) CHARACTER SET ascii

Batch chèn của bạn - 100 tại một thời điểm sẽ chạy nhanh gấp 10 lần. (Vượt quá 100 đang nhận được 'lợi nhuận giảm dần'.)

Giá trị của autocommit là gì? Bạn có đang gói từng CHERTN trong BEGIN ... CAM KẾT không? Giá trị của innodb_flush_log_at_trx_commit là gì?


Làm thế nào để tôi có được chèn theo đợt nếu dữ liệu được chèn qua nguồn bên ngoài như các máy khách khác nhau với các giá trị khác nhau .... nó có đáng tin cậy không nếu tôi sử dụng: codechèn vào các giá trị t_name (col1, col2, col3) (val1, val2, val3), (val1, val2, val3), (val1, val2, val3), (val1, val2, val3), (val1, val2, val3); code
Shashank

1

Thiết lập một hàng đợi. Ứng dụng sẽ ghi vào hàng 1 hàng một lần và sau đó lấy hàng ra và chèn vào cơ sở dữ liệu theo lô dựa trên số lượng hàng trong khoảng thời gian đã trôi qua kể từ lần chèn cuối cùng.

Tôi đã thấy nơi mà việc chèn 10.000 lần một lúc là nhanh nhất, vì vậy bạn sẽ cần phải kiểm tra để tìm ra một điểm ngọt ngào.

Bạn có thể tạo hệ thống xếp hàng đơn giản của riêng bạn hoặc sử dụng hệ thống xếp hàng hiện có. Dưới đây là một số ví dụ: HornetQFile :: Queue . Dưới đây là một bài đăng trên SE liệt kê một số tùy chọn tốt khác: Hàng đợi tin nhắn trong perl, php, python .


Tôi đồng ý với cách tiếp cận này - Tôi đang xử lý ~ 1500 lần chèn cứ sau 5 giây trên một ứng dụng và đó là phụ thứ hai. mysql dường như có một số cơ chế được triển khai trong nội bộ khiến cho việc chèn hàng loạt xảy ra thực sự thực sự nhanh chóng.
Don Wool
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.