Xóa và lấy lại không gian từ bảng InnoDB


14

Tôi có một bảng InnoDB 700GB mà tôi không ghi thêm bất kỳ dữ liệu nào (chỉ đọc). Tôi muốn xóa dữ liệu cũ hơn và giữ lại không gian đĩa đó (vì tôi sắp hết dữ liệu). Phần xóa khá dễ dàng, vì tôi có một chỉ mục chính tự động, vì vậy tôi chỉ có thể lặp lại trong các khối bằng cách sử dụng nó và xóa các hàng, nhưng điều đó sẽ không đưa tôi trở lại không gian. Tôi giả sử OPTIMIZE TABLEsẽ nhưng điều đó có thể mất mãi mãi trên một bảng 700 GB, vậy có lựa chọn nào khác mà tôi đang xem không?

Chỉnh sửa bởi RolandoMySQLDBA

Giả sử bảng của bạn là mydb.mytable, vui lòng chạy truy vấn sau và đăng nó ở đây để bạn có thể xác định không gian đĩa cần thiết cho độ co của bảng:

SELECT
    FORMAT(dat/POWER(1024,3),2) datsize,
    FORMAT(ndx/POWER(1024,3),2) ndxsize,
    FORMAT((dat+ndx)/POWER(1024,3),2) tblsize
FROM (SELECT data_length dat,index_length ndx
FROM information_schema.tables WHERE
table_schema='mydb' AND table_name='mytable') A;

Chúng ta cũng cần xem cấu trúc bảng, nếu được phép.

Chỉnh sửa bởi Noam

Đây là đầu ra của truy vấn:

datsize ndxsize tblsize
682,51 47,57 730,08

Đây là cấu trúc bảng ( SHOW CREATE TABLE)

`CREATE TABLE `mybigtable` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL,  
  `created_at` datetime NOT NULL,  
  `tid` bigint(20) NOT NULL,  
  `text` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
  `ft` tinyint(1) NOT NULL,  
  `irtsd` bigint(20) NOT NULL,  
  `irtuid` int(11) NOT NULL,  
  `rc` int(11) NOT NULL,  
  `r` tinyint(1) NOT NULL,  
  `e` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,  `timezone` varchar(5) NOT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `uid_tid` (`uid`,`tid`)) ENGINE=InnoDB AUTO_INCREMENT=2006963844 DEFAULT CHARSET=utf8`

Bạn có một ổ đĩa khác để chỉ bắt dữ liệu không ???
RolandoMySQLDBA

@RolandoMySQLDBA Tôi có một ổ cứng gắn ngoài tôi có thể gắn kết. Có tính không?
Noam

@RolandoMySQLDBA nhưng tất nhiên sẽ giống như một tùy chọn xóa một số dung lượng mà không cần phải có thêm 700GB
Noam

@RolandoMySQLDBA kích thước đĩa thêm có gây ra bất kỳ vấn đề hiệu suất nào không?
Aris

@Aris nó có thể phụ thuộc vào đĩa và thời gian tìm kiếm của nó. Ngày nay, hầu hết các đĩa hoạt động tốt hơn bây giờ, nhưng điều tốt là lãng phí chu kỳ (thậm chí sẽ rất nhanh) nếu bạn có các túi đĩa lớn thưa thớt trong bảng ???. Điều này đặc biệt đúng với InnoDB thường được cố định ở các khối 16K. Với sự phân mảnh bên trong của các khối 16K, bạn có thể muốn chống phân mảnh bảng bằng cách sử dụng ALTER TABLE ... ENGINE=InnoDB;(nếu bạn có phòng để làm điều đó). Hầu hết chỉ hài lòng với ổ SSD rất nhanh của họ và sẽ không còn lo lắng nữa.
RolandoMySQLDBA

Câu trả lời:


21

Đây là một câu hỏi hay. Bạn có một vài giải pháp nhưng bàn của bạn khá lớn nên sẽ không có gì là không đau :)

Bạn có ba giải pháp để "thu nhỏ" các bảng InnoDB:

1. BẢNG TỐI ƯU

Bạn có thể sử dụng OPTIMIZE TABLEnhư bạn đã đề cập nhưng bạn nên quan tâm đến innodb_file_per_tablebiến:

mysql> show variables like "innodb_file_per_table";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.00 sec)

Hãy để tôi giải thích:

Các OPTIMIZE TABLEbảng InnoDB, khóa bảng, sao chép dữ liệu trong một bảng sạch mới (đó là lý do tại sao kết quả bị thu hẹp), bỏ bảng gốc và đổi tên bảng mới với tên ban đầu. Đó là lý do tại sao bạn nên quan tâm để có gấp đôi thể tích của bảng trong đĩa của mình (Trong quá trình hoạt động, bạn sẽ cần 2x700GB).

Khi bạn ở trong innodb_file_per_table = ON. Tất cả các bảng có tập tin dữ liệu thích hợp. Vì vậy, OPTIMIZEcâu lệnh sẽ tạo một tệp dữ liệu mới (~ 700GB) khi hoạt động kết thúc, MySQL sẽ bỏ tệp gốc và đổi tên tệp mới (vì vậy cuối 700GB - có thể ít hơn vì nó sẽ bị thu hẹp - dữ liệu được tạo trong quá trình hoạt động sẽ được phát hành)

Khi bạn ở trong innodb_file_per_table = OFF. Tất cả dữ liệu đi đến một tệp dữ liệu: ibdata . Tập tin này có một đặc điểm đáng buồn, nó không thể được thu nhỏ. Vì vậy, trong OPTIMIZEquá trình này, bảng mới của bạn sẽ được tạo (gần 700 GB ), nhưng ngay cả sau khi hoạt động thả và đổi tên (và kết thúc OPTIMIZEgiai đoạn), ibdata của bạn sẽ không phát hành ~ 700 GB , vì vậy bạn muốn có một số dữ liệu miễn phí nhưng bạn có 700 GB Hơn nữa, tuyệt không?

2. BẢNG BẢNG

Bạn cũng có thể sử dụng một ALTER TABLEtuyên bố, ý ALTER TABLEchí sẽ làm việc theo cách tương tự như OPTIMIZE TABLE. Bạn chỉ có thể sử dụng:

ALTER TABLE myTable EGINE=InnoDB;

3. BẢNG TAY (TRỰC TUYẾN)

Vấn đề OPTIMIZEALTER TABLEnó khóa bảng trong khi hoạt động. Bạn có thể sử dụng công cụ Percona: pt-online-giản đồ thay đổi (từ Percona Toolkit: link ). pt-online-lược đồ ... sẽ xây dựng một mecanism với các trình kích hoạt và bảng tạm thời mà bạn cho phép bảng gốc có sẵn để đọc và ghi trong quá trình hoạt động. Tôi sử dụng công cụ này trong sản xuất cho ALTERnó lớn, nó khá tuyệt.

Lưu ý rằng bạn nên FOREIGN KEYtham chiếu đến bảng của bạn, FK và kích hoạt rủi ro để tạo ra một mớ hỗn độn. Để kiểm tra điều kiện tiên quyết này, truy vấn:

mysql> SELECT COUNT(*) FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE REFERENCED_TABLE_NAME = "myTable";
+----------+
| COUNT(*) |
+----------+
|        0 |
+----------+
1 row in set (0.04 sec)

Đây là cách tôi sử dụng pt-online-giản đồ-thay đổi:

pt-online-schema-change --alter "ENGINE=InnoDB" D=myBase,t=myTable --user --ask-pass

Lưu ý rằng lưu ý của tôi về innodb_file_per_table cũng đúng với giải pháp này.

4. mysqldump

Giải pháp cuối cùng là tạo lại tất cả các cơ sở dữ liệu từ một bãi chứa. Dài khủng khiếp, nhưng hiệu quả khủng khiếp. Lưu ý rằng đó là giải pháp duy nhất để "thu nhỏ" tệp ibdata.

Tối đa


Ngoài ra trong tùy chọn bảng thay đổi trực tuyến công cụ percona tôi sẽ cần 700GB dung lượng đĩa trống?
Noam

Vâng, pt-online chỉ cần sử dụng một số mecanism để thực hiện ALTER trực tuyến nhưng dù sao nó cũng tạo ra một ALTER.
Maxime Fouilleul

@MaximeFouilleul kích thước đĩa thêm có gây ra bất kỳ vấn đề hiệu suất nào không?
Aris

1

Nếu bạn thiếu kích thước đĩa, tôi sẽ đề nghị bạn làm giống như Max được đề xuất với pt-online-giản đồ thay đổi (ONLINE). Tôi đã ở trong tình huống tương tự với một bảng nhỏ hơn nhiều (200 GB) và chọn thực hiện một số thao tác nén cùng một lúc. Một cái gì đó dọc theo dòng này sẽ hoạt động:

pt-online-schema-change --alter="ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4" D=myBase,t=myTable --user --ask-pass

Điều này sẽ chỉ hoạt động nếu bạn ở định dạng tệp barracuda và ở định dạng COMPACT của bảng. Ngoài ra, bạn phải kích hoạt innodb_file_per_table. Điều này có thể làm tuyệt vời kích thước của bảng của bạn đặc biệt là nếu có nhiều văn bản và nếu bạn sử dụng KEY_BLOCK_SIZE nhỏ hơn như 8K hoặc thậm chí 4K (mặc định là 16K). Bạn cũng có thể kiểm tra xem bạn có thể đạt được bao nhiêu dung lượng từ nhiều điểm chuẩn liên quan đến vấn đề này trên các blog khác nhưng tài liệu MySQL quảng cáo 25% đến 50% (đối với tôi là gần 90%).

Lưu ý rằng điều này cũng có thể ảnh hưởng đến hiệu suất khi thực hiện CHỌN (từ tài liệu MySQL):

Do đó, tại bất kỳ thời điểm nào, nhóm bộ đệm có thể chứa cả dạng nén và dạng không nén của trang hoặc chỉ dạng nén của trang hoặc không.

MySQL cũng phải giải nén dữ liệu khi không nằm trong vùng đệm. Vì vậy, được cảnh báo.

Điều này đã thực sự làm việc tốt trong trường hợp của tôi. Tôi đã có một văn bản dài. 200GB trở thành 26GB. Biểu diễn không bị thay đổi.

Để biết thêm thông tin chi tiết, hãy kiểm tra các liên kết sau:

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-usage.html

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-i INTERNals.html

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.