Tại sao sử dụng innodb_file_per_table?


26

Có rất nhiều bài viết phóng đại (tất nhiên IMHO) cần innodb_file_per_table. Tôi hiểu rằng với innodb_file_per_table, nên có sự kiểm soát tốt hơn đối với các bảng riêng lẻ; như sao lưu từng bảng riêng biệt. Tuy nhiên, yêu cầu cho hiệu suất tốt hơn là nghi vấn.

Trong thử nghiệm của tôi, không có sự khác biệt về hiệu suất innodb_file_per_tableibdata1cho cơ sở dữ liệu 60GB. Tất nhiên, đó là một thử nghiệm đơn giản với các truy vấn bình thường và tình huống có thể khác đối với các truy vấn phức tạp trong cuộc sống thực (đây là lý do mà tôi đã hỏi câu hỏi này). Linux 64-bit có ext4thể xử lý hiệu quả các tệp lớn.

Với innodb_file_per_table, cần nhiều thao tác I / O đĩa hơn; và điều này rất có ý nghĩa trong các phức tạp JOINvà các FOREIGN KEYràng buộc.

Không gian bảng được chia sẻ trên đơn ibdata; làm thế nào các không gian bảng chuyên dụng cho các bảng riêng biệt có thể tiết kiệm không gian đĩa? Tất nhiên, sẽ dễ dàng hơn để giải phóng không gian bảng cho mỗi bảng ALTER, nhưng nó vẫn là một quá trình đắt tiền (có khóa bảng).

HỎI:innodb_file_per_tableảnh hưởng đến hiệu suất tốt hơn của mysql không? Nếu đúng thì tại sao?


Xem câu trả lời này cho câu hỏi của tôi: dba.stackexchange.com/questions/7924/ cũng có thể giúp đỡ.
KM.

Câu trả lời:


19

Tôi không nghĩ đó là vấn đề hiệu suất mà là quản lý.

Với tệp riêng cho mỗi bảng, bạn có thể lưu trữ các cơ sở dữ liệu khác nhau trong các thiết bị lưu trữ khác nhau chẳng hạn.

Bạn có thể xử lý trường hợp cơ sở dữ liệu rất lớn trong các hệ thống tệp không thể xử lý các tệp lớn (ít nhất là hoãn sự cố cho đến khi một bảng đạt đến giới hạn kích thước tệp).

Bạn không có sự tăng trưởng không gian bảng không kiểm soát. Nếu bạn có một số bảng lớn mà bạn thả, ibdatatệp vẫn nhỏ.

Một khía cạnh có thể có một số ảnh hưởng đến hiệu suất là sự phân mảnh dữ liệu và chỉ mục của bảng, sẽ bị giới hạn trên mỗi bảng. Nhưng điều đó cần thử nghiệm để được xác nhận.


Sự tăng trưởng không gian bảng chính xác là lý do tại sao bạn muốn innodb_file_per_table.
sjas

13

Tại sao sử dụng innodb_file_per_table?

Bởi vì việc quản lý cá nhân dễ dàng hơn vì nó có thể được thực hiện ở cấp độ tệp. Điều này có nghĩa là ngay cả khi máy chủ ngừng hoạt động, bạn vẫn có thể sao chép dữ liệu bằng cách sao chép các tệp bảng trong khi sử dụng không gian bảng dùng chung có nghĩa là sao chép mọi thứ có thể lớn không cần thiết hoặc tìm cách để máy chủ chạy để trích xuất dữ liệu ( bạn thực sự không muốn trích xuất dữ liệu theo cách thủ công với trình soạn thảo hex).

Ai đó đã cảnh báo rằng bạn không thể đơn giản sao chép và dán .ibdtệp từ máy chủ này sang máy chủ khác. Điều này có thể đúng, nhưng nó không nên áp dụng cho các bản sao lưu trên cùng một máy chủ (tôi đang sử dụng thuật ngữ sao lưu ở đây theo nghĩa truyền thống là tạo một bản sao; nghĩa là không thay đổi mạnh mẽ toàn bộ). Hơn nữa, ibdata1được tự động tạo lại khi khởi động (như đã thấy trong bước xóaibdata1 của hầu hết các chuyển đổi mã hóa thành hướng dẫn tập tin trên mỗi bảng). Như vậy, bạn không cần phải sao chép ibdata1thêm vào các .ibdtệp của mình (và các tệp tương ứng .frm, v.v.).

Nếu cố gắng để phục hồi một bảng bị mất, nó phải là đủ để sao chép nó .ibd.frmtập tin, cũng như information_schema(đó là nhiều nhỏ hơn ibdata1). Bằng cách đó, bạn có thể đặt chúng vào một máy chủ giả và trích xuất bảng của bạn mà không phải sao chép toàn bộ, đồ sộ.

Tuy nhiên, yêu cầu cho hiệu suất tốt hơn là nghi vấn. Tập hợp với innodb_file_per_table, cần nhiều thao tác I / O đĩa hơn; và điều này rất có ý nghĩa trong các ràng buộc phức tạp THAM GIA và NGOẠI TỆ.

Không có gì đáng ngạc nhiên, hiệu suất sẽ phụ thuộc hoàn toàn vào (các) cơ sở dữ liệu cụ thể được sử dụng. Một người sẽ có (thậm chí rất nhiều) kết quả khác nhau từ người khác.

Đúng là sẽ có nhiều thao tác I / O đĩa hơn với tệp trên mỗi bảng, nhưng chỉ nhiều hơn một chút . Hãy suy nghĩ về cách hệ thống hoạt động.

  • Đối với cơ sở dữ liệu nguyên khối:

    1. Máy chủ được khởi động
    2. ibdata1 được mở
    3. Tiêu đề và siêu dữ liệu được đọc
    4. Cấu trúc và siêu dữ liệu được lưu trữ trong bộ nhớ
    5. Truy vấn xảy ra
      1. Máy chủ truy cập vào đĩa và đọc dữ liệu từ đã mở ibdata1
      2. Máy chủ có thể lưu trữ dữ liệu trong bộ nhớ
  • Đối với cơ sở dữ liệu trên mỗi bảng:

    1. Máy chủ được khởi động
    2. ibdata1 được mở
    3. Tiêu đề và siêu dữ liệu được đọc
    4. Mỗi .ibdtệp riêng lẻ được mở
    5. Tiêu đề và siêu dữ liệu được đọc từ mỗi .ibdtệp
    6. Cấu trúc và siêu dữ liệu được lưu trữ trong bộ nhớ
    7. Truy vấn xảy ra
      1. Máy chủ truy cập đĩa và đọc dữ liệu từ .ibdtệp đã mở
      2. Máy chủ có thể lưu trữ dữ liệu trong bộ nhớ

Bạn sẽ nhận thấy rằng khi máy chủ đang chạy, bạn không thể di chuyển các tệp dữ liệu vì máy chủ có các thẻ điều khiển mở cho chúng. Điều này là bởi vì khi nó khởi động, nó mở chúng và để chúng mở. Nó không mở và đóng chúng cho từng truy vấn riêng lẻ.

Như vậy, chỉ có một số hoạt động I / O nữa khi bắt đầu, khi máy chủ khởi động; không phải trong khi nó đang chạy Hơn nữa, trong khi mỗi .ibdtệp riêng lẻ có chi phí riêng (chữ ký tệp, cấu trúc, v.v.), chúng được lưu trong bộ nhớ và không được đọc lại cho mỗi truy vấn. Hơn nữa, các cấu trúc tương tự được đọc ngay cả với một không gian bảng được chia sẻ, do đó hầu như không có bất kỳ bộ nhớ nào (nếu có).

Liệu innodb_file_per_table có ảnh hưởng đến hiệu suất tốt hơn của mysql không?

Trên thực tế, nếu có bất cứ điều gì, hiệu suất trong thực tế có thể tồi tệ hơn .

Khi sử dụng một không gian bảng được chia sẻ, các hoạt động đọc và ghi đôi khi có thể / thường được kết hợp để máy chủ đọc một mẫu dữ liệu từ nhiều bảng trong một lần ibdata.

Tuy nhiên, nếu dữ liệu được trải ra giữa nhiều tệp, thì nó phải thực hiện một thao tác I / O riêng cho từng tệp riêng lẻ.

Tất nhiên điều này một lần nữa hoàn toàn phụ thuộc vào cơ sở dữ liệu trong câu hỏi; tác động hiệu suất trong thế giới thực sẽ phụ thuộc vào kích thước, tần suất truy vấn và phân mảnh bên trong của không gian bảng được chia sẻ. Một số người có thể nhận thấy một sự khác biệt lớn trong khi những người khác có thể không thấy bất kỳ tác động nào cả.

Không gian bảng được chia sẻ trên ibdata đơn; làm thế nào các không gian bảng chuyên dụng cho các bảng riêng biệt có thể tiết kiệm không gian đĩa?

Nó không. Nếu bất cứ điều gì, nó làm tăng việc sử dụng đĩa một số.

Tôi không có cơ sở dữ liệu 60 GB để kiểm tra, nhưng cơ sở dữ liệu cá nhân của tôi có chứa cài đặt WordPress và một vài bảng nhỏ để sử dụng cá nhân và kiểm tra phát triển có trọng lượng ~ 30 MB trong khi sử dụng không gian bảng dùng chung. Sau khi chuyển đổi nó thành tệp trên mỗi bảng, nó tăng lên ~ 85 MB. Ngay cả khi bỏ mọi thứ và nhập lại, nó vẫn> 60MB.

Sự gia tăng này là do hai yếu tố:

  • Các tối thiểu tuyệt đối kích thước cho ibdata1là-vì một lý do-10MB, ngay cả khi bạn không có gì nhưng information_schemađược lưu trữ trong đó.

  • Với một không gian bảng được chia sẻ, chỉ ibdata1có chi phí chung như chữ ký tệp, siêu dữ liệu, v.v., nhưng với mỗi bảng, mỗi .ibdtệp riêng lẻ có tất cả những thứ đó. Điều này có nghĩa là tổng số (ngay cả với giả thuyết <10 MB ibdata1) sẽ có phần lớn hơn ít nhất:

    GetTotalSizeofOverhead() * GetNumTables()

Rõ ràng những thứ này sẽ không tăng rất nhiều (trừ khi bạn đang sử dụng máy chủ giới hạn kích thước cơ sở dữ liệu của bạn hoặc lưu trữ chúng trên ổ đĩa flash, v.v.), nhưng dù sao chúng cũng tăng lên và bằng cách chuyển bảng ( mọi ) sang tệp -per-bàn bạn có thể thu nhỏ ibdata1xuống còn 10MB, tổng cộng sẽ luôn luôn nhiều hơn so với trước đây.


11

Đây là lý do của tôi để LUÔN LUÔN sử dụng innodb_file_per_table:

Không có tệp trên mỗi bảng, tệp ibdata không bao giờ nén hoặc thu nhỏ hoặc giảm bớt trong không gian bao giờ. Không phải khi bạn xóa một hàng, thả bảng hoặc cơ sở dữ liệu. 2GB dữ liệu có thể trở thành một tệp 20 GB ngay lập tức nếu bạn có một hệ thống xếp hàng hoạt động.

Giả sử bạn muốn tạo bản sao lưu của bảng 1GB hiện tại của mình trước khi thay đổi, sau đó loại bỏ nó sau đó. Bạn đang bị mắc kẹt với một GB không gian chưa sử dụng trong ibdata của bạn. Bummer.

Có thể có những ví dụ vô tận về các trường hợp trong đó các biện pháp tạm thời làm tăng tệp dữ liệu đơn lẻ, nhưng đủ để nói rằng theo tôi, không bao giờ có lý do để KHÔNG sử dụng innodb_file_per_table

Ngoài ra, đây là một bài viết tốt để đọc: http://code.openark.org/blog/mysql/reasons-to-use-innodb_file_per_table


1
Tôi nhận ra rằng cũng tốt để LUÔN làm điều đó. Mảng lưu trữ từ tính được hỗ trợ bởi SSD có thể xử lý bộ đệm đọc / ghi hiệu quả hơn đối với các tệp nhỏ hơn cho các bảng. Đối với một loạt các bảng mà% 99,99 thời gian chỉ nhận được 'đọc' nhưng không được viết, chúng luôn nằm trong bộ đệm của bộ điều khiển lưu trữ, giúp giảm đáng kể thời gian phản hồi.
sdkks

5

Lý do của tôi tại sao không sử dụng innodb_file_per_table là hiệu suất.

Tôi đã thực hiện một số thử nghiệm cho cơ sở dữ liệu của chúng tôi với 450 bảng trên phiên bản mysql 5.5.45 Linux CentOS 6.7

Đối với các thử nghiệm đơn vị chèn đồ đạc vào cơ sở dữ liệu trước mỗi thử nghiệm (không sử dụng tất cả các bảng mọi lúc) và cũng kiểm tra chính nó hoạt động với cơ sở dữ liệu rất nhiều (chèn, cập nhật, xóa, chọn) hiệu suất tốt hơn 3-5 lần khi các bảng cơ sở dữ liệu không tách thành nhiều tập tin hơn

Tôi khuyên bạn nên kiểm tra cơ sở dữ liệu của mình với các truy vấn bạn muốn sử dụng và so sánh nó trước khi bạn quyết định sử dụng innodb_file_per_table

Có thể bạn có thể phát hiện ra rằng đối với máy chủ sản xuất, bạn có thể sử dụng innodb_file_per_table nhưng đối với môi trường CI (tiếp tục tích hợp) để bắt đầu kiểm tra đơn vị (sử dụng DB rất nhiều) và các nhà phát triển bắt đầu kiểm tra đơn vị rất nhiều không nên sử dụng vì hiệu suất.


2
Tôi đoán điều này là do thời gian cần thiết để phân bổ các tệp ban đầu cho tất cả 450 bảng so với phân bổ một tệp duy nhất. Trong sản xuất, điều này sẽ chỉ xảy ra một lần vì vậy không phải là một vấn đề, nhưng bạn nên lưu ý rằng để nhanh chóng tạo cơ sở dữ liệu và sau đó xé nó hoàn toàn và lặp đi lặp lại nhiều lần một tệp ibdata sẽ tốt hơn.
ColinM

2

Nó làm cho dữ liệu dễ quản lý hơn vì bạn có thể lấy lại không gian chưa sử dụng, điều này thật tuyệt.

Tôi nghĩ rằng nếu cơ sở dữ liệu của bạn được sử dụng chủ yếu cho các truy vấn chọn thì nó sẽ không ảnh hưởng nhiều đến hiệu suất. Nó vẫn phải đọc về cùng một lượng dữ liệu. Tôi không nghĩ nó quan trọng đến việc tập tin đọc dữ liệu từ đâu.

Tuy nhiên, nó có thể làm cho hiệu suất kém hơn trên cơ sở dữ liệu có nhiều phần chèn và cập nhật. Điều này là do mysql gọi fsync () trên tệp lưu trữ sau khi bạn thực hiện giao dịch. Nếu có một tệp duy nhất, nó thực hiện một cuộc gọi và chờ cuộc gọi hoàn tất. Nếu có nhiều tệp, nó phải thực hiện cuộc gọi nhiều lần và đợi tất cả các cuộc gọi đó trở lại trước khi lệnh commit có thể quay lại.

Đây là một bài đăng từ một người có kinh nghiệm về vấn đề này: http://umangg.blogspot.com/2010/02/innodbfilepertable.html


2

Theo bài viết dưới đây, hiệu suất không phải là về việc quản lý dữ liệu (chính hoạt động thô sơ) mà là về việc tạo và loại bỏ các đối tượng.

innodb_file_per_table làm cho việc tạo và thả các đối tượng chậm hơn so với lưu trữ ibdata và để sản xuất không áp dụng được nhưng đối với thử nghiệm liên tục nên có liên quan.

https://www.percona.com/blog/2015/02/24/mysqls-innodb_file_per_table-slowing/


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.