Chia bảng trong MySQL. Thực hành tốt?


14

Tôi đã bắt đầu làm việc với một dự án hiện có và nhà phát triển trước đó đã chia một bảng thành 10 bảng riêng biệt với các lược đồ giống hệt nhau nhưng dữ liệu khác nhau.

Các bảng trông như thế này:

[tableName_0]
[tableName_1]
[tableName_2]
[tableName_3]
[tableName_4]
[tableName_5]
[tableName_6]
[tableName_7]
[tableName_8]
[tableName_9]

Khóa chính là một idtrường số nguyên . Ứng dụng sử dụng thuật toán băm ( idmod 10) để biết bảng nào sẽ truy cập khi thực hiện tra cứu. Ví dụ id= 10 sẽ dẫn đến [tableName_0].

Kết hợp lại, các bảng có thể có 100.000 hàng và tốc độ tăng trưởng tương đối thấp.

Vì vậy, câu hỏi của tôi là liệu đây có phải là một giải pháp khả thi hay thậm chí nếu đó là một thực tiễn tốt trong mọi tình huống. Lý thuyết của tôi là thúc đẩy để có chúng kết hợp vì nó sẽ làm cho mọi thứ dễ dàng hơn như UNIONs, v.v. Nhược điểm chính là thay đổi tất cả các mã ứng dụng và liệu nó có đáng giá về lâu dài hay không.

Câu trả lời:


16

Tôi nghĩ rằng tất cả mọi người đang quá phức tạp này. Điểm mấu chốt ở đây là:

Kết hợp lại, các bảng có thể có 100.000 hàng và tốc độ tăng trưởng tương đối thấp.

Đây là một miếng bánh cho bất kỳ RDBMS nào để xử lý. Đi với một bảng, lập chỉ mục cho đúng và coi đó là một vấn đề được giải quyết.

Bạn không cần phải xem xét phân vùng, cho dù là "tự chế" hay nói cách khác, cho đến khi bạn bắt đầu xử lý khối lượng dữ liệu cực lớn - nghĩ hàng tỷ hàng trở lên.


3

Bạn có thể sử dụng các bảng hợp nhất, tuy nhiên chúng cổ hơn từ các phiên bản 4.x. Do ứng dụng của bạn được phân vùng thủ công vì đây là một) bạn đang chạy phiên bản thực sự cũ hoặc b) nhà phát triển ban đầu không biết về phân vùng bảng.

Nói tóm lại, nếu bạn đang chạy 5.1+, bạn có thể để mysql thực hiện phân vùng này cho bạn. Xem http://dev.mysql.com/doc/refman/5.1/en/partitioning.html Nếu bạn đang sử dụng 5.5, bạn nên kiểm tra các tài liệu cụ thể đó vì bạn sẽ tìm thấy một số khác biệt.

Có nhiều lợi thế để phân vùng. Tuy nhiên, nó thực sự phụ thuộc vào bộ dữ liệu trong tay, các mẫu truy cập và cách lập chỉ mục. Ngoài ra, hãy ghi nhớ các nhận xét sau đây của tôi trong bối cảnh phân vùng mysql 5+, KHÔNG phải các bảng Hợp nhất mysql cũ hơn; mặc dù đôi khi chúng được thảo luận về các phân vùng.

Vài ví dụ:

  • Khóa thẳng (băm) dựa trên khóa tra cứu thường xuyên truy cập. Nếu bạn luôn luôn tìm kiếm bằng một khóa chính hoặc khóa duy nhất khác thì mysql có thể cắt không gian tìm kiếm theo hệ số bao nhiêu phân vùng bạn có. Lưu ý tuy nhiên điều này có thể gây bất lợi nếu bạn phân vùng theo một khóa và sau đó thường xuyên tìm kiếm theo khóa khác. Nếu bạn tìm kiếm theo một khóa, dữ liệu không được phân vùng theo thì nó phải thực hiện nhiều tìm kiếm hơn trên các tra cứu (một cho mỗi phân vùng, b / c thẳng thắn, nó không biết dữ liệu ở đâu)
  • Hãy xem xét các tình huống là bạn có một bộ hồ sơ tạm thời phát triển theo ngày và bạn định kỳ cắt tỉa tháng trước. Nếu bạn đang phân vùng theo ngày thì bạn có thể chỉ cần bỏ một phân vùng nhanh như thả bảng, bất kể lớn như thế nào. Nếu bạn muốn cắt tỉa một bảng như vậy theo ngày, bạn phải đưa ra một hoặc nhiều truy vấn XÓA trong đó mỗi hàng riêng lẻ sẽ bị xóa. Nhược điểm của điều này là mysql không tự động tạo các phân vùng mới sau khi bạn đạt đến ngày tối đa bạn đã tính trong kịch bản này; bạn cần thêm các kịch bản bảo trì được xây dựng trên phần của bạn để thêm các phân vùng khi chúng cần thiết.
  • Nếu bạn đang sử dụng kiểm tra myisam và phục hồi nhanh hơn nhiều. Hãy xem xét một bảng myisam 100G. Nếu bạn muốn khôi phục một bảng bị hỏng, bạn sẽ cần ít nhất khoảng 100G dung lượng đĩa dự phòng. Nếu nó được phân chia thành 10 khối khác nhau có kích thước bằng nhau thì bạn chỉ cần 10G dung lượng (và ít bộ nhớ key_sort_buffer để phục hồi nhanh); nhưng sẽ cần phải lặp lại cho mỗi phân vùng.

Vì vậy, tóm lại, cách tiếp cận chung của các bảng phân vùng có thể mang lại nhiều lợi ích. Tuy nhiên, đó không phải là một viên đạn ma thuật được áp dụng một cách mù quáng mà không xem xét đến các mẫu truy cập và cách chính xác bạn đang phân vùng.

Tôi có thể tưởng tượng các tình huống trong đó phân vùng mong muốn rất cụ thể cho ứng dụng và sẽ phù hợp hơn để có logic đó trong lớp ứng dụng. Tuy nhiên, với mô tả 10 mô-đun thẳng của bạn, điều này không giống như trường hợp như vậy.

BIÊN TẬP

Khi viết lên mô tả của tôi, tôi quên rằng bạn đã nêu bảng của bạn là 100K hàng. Với lược đồ đầy đủ của bảng và chiều dài hàng trung bình, thật khó để nói chắc chắn, nhưng nói chung, âm thanh có kích thước trung bình ngay cả đối với phần cứng khiêm tốn. Đồng thời, nếu nó không gây ra vấn đề như hiện tại hoặc trong tương lai gần thì đừng dành thời gian và đưa ra rủi ro bằng cách thay đổi nó.


3

Những gì nhà phát triển trước đó đã làm cho bạn là xây dựng triển khai phân vùng theo hàm băm của riêng họ. MySQL thực sự hỗ trợ điều này tự nhiên từ MySQL 5.1:

http://dev.mysql.com/doc/refman/5.1/vi/partitioning-hash.html

Tôi không thể nghĩ ra một lý do chính đáng để thực hiện phân vùng theo hàm băm của riêng bạn thay vì dựa vào phiên bản gốc [1]. Thực hiện thay đổi lược đồ sẽ là một cơn ác mộng.

Tôi cũng hiếm khi đề xuất phân vùng theo hàm băm (triển khai riêng). Tôi nghĩ nó sẽ hữu ích nếu bạn có thể sử dụng nó để tìm kiếm song song từng phân vùng cùng một lúc (điều mà MySQL sẽ không làm). Nếu bạn cần tìm kiếm trên nhiều phân vùng, lược đồ bạn đã mô tả thường sẽ chậm hơn nhiều.

[1] Tuy nhiên, đối với một số loại phân vùng khác, có thể có ý nghĩa để cuộn phân vùng của riêng bạn. MySQL buộc bạn phải biến khóa phân vùng thành một phần của khóa chính và tất cả các chỉ mục duy nhất.


2

Trả lời câu hỏi:

liệu đây có phải là một giải pháp khả thi hay không

IMHO, Điều này có vẻ như không cần thiết. Bạn chỉ có thể lập chỉ mục và phân vùng một bảng đúng trừ khi có một số thông tin khác không được tiết lộ trong mô tả.

Trả lời câu hỏi:

... nếu đó là một thực hành tốt trong mọi tình huống

IMHO, shending dọc có thể có ý nghĩa tùy thuộc vào bối cảnh. Khi tôi thấy điều này, nó thường ở dạng nhật ký. Hãy giả vờ rằng chúng tôi đang sử dụng điều này cho nhật ký máy chủ web và chúng tôi muốn phân vùng theo tháng. Thay vì thay đổi một bảng hiện có tại chỗ mỗi ngày, chúng ta có thể tạo một bảng mới mỗi ngày và đăng nhập các hàng vào bảng đó.

ví dụ: Giả sử bảng nhật ký web có thể có dạng:

datetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
uri VARCHAR(1024),
host VARCHAR(255),
user_agent VARCHAR(255),
etc...

Giải pháp của bạn tạo các bảng khi cần thiết trong cơ sở dữ liệu weblog:

weblogs.20120301
weblogs.20120302
weblogs.20120303

Vân vân.

Bằng cách này, dữ liệu vẫn có thể duy trì và tìm kiếm được. Khai thác trở thành một quá trình định kỳ bình thường. Hoạt động liên tục không bị khóa bởi các hoạt động trên dữ liệu cũ.

Trong kịch bản bạn đã trình bày, dù sao bạn cũng bị khóa trong một cấu trúc, vậy tại sao không sử dụng một bảng duy nhất được tối ưu hóa cho mục đích này? Thuật toán lưu trữ dựa trên các hàng có vẻ sơ sài và dễ bị lỗi.


0

Nếu một truy vấn nhắm mục tiêu dữ liệu khổng lồ, việc phân chia dữ liệu theo các điều kiện truy vấn sẽ có sự cải thiện đáng chú ý về hiệu suất. Nhưng sự phân chia như vậy, như bạn đã thấy, đưa một số vấn đề về lập trình lên.

Vì vậy, câu hỏi là: sự phân chia đó có giá trị cho hiệu suất, hoặc nó gây hại cho hiệu suất?

Nếu bạn có một giao dịch cần khóa nhiều hàng trên một số bảng và có vấn đề trên đó (ví dụ: bế tắc hoặc hết thời gian giao dịch), bạn có thể muốn kết hợp chúng thành một bảng duy nhất và viết lại SQL để sửa chữa các vấn đề.

Khi tôi suy nghĩ về việc có nên chia bảng hay không, tôi thường cân nhắc sự đánh đổi giữa việc tăng hiệu năng và độ phức tạp của lập trình.

Trong tình huống của bạn, việc sửa đổi mã hiện tại có thể là một giải pháp lâu dài để giúp mã dễ bảo trì hơn. Tôi sẽ đề nghị thử lập trình meta. Ví dụ: sử dụng StringTemplate để tạo SQL động. Tôi muốn tạo SQL từ công cụ lập trình meta nếu việc sửa đổi mã hiện tại quá khó.


0

Khi bạn cần lưu trữ các tệp trong bảng, để sử dụng phép đo này giúp xuất, sửa chữa và khôi phục.

Tôi có các bảng có> 30 Gb được phân vùng trong 10 bảng. Các bảng này chỉ có ID - BLOB và với tôi là dễ dàng để giữ. Và tôi sử dụng MyISAM để lưu bộ đệm INNODB.

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.