Thiết kế database MySQL từ con số 0
Mysql
45
Database
24
White

ShinaBR2 viết ngày 07/07/2017

Vào một ngày đẹp trời, khi bạn nhận được yêu cầu phải thiết kế database cho một hệ thống, câu hỏi đầu tiên được đặt ra, quy trình làm ra nó sẽ cụ thể gồm những bước như thế nào? Bài viết này phù hợp cho những bạn mới như mình, hi vọng sẽ giúp bạn hiểu được cách thiết kế một database đi theo những bước như thế nào và giả sử nếu trường hợp bạn rơi vào tình huống này cũng dễ xử. Mình là lập trình viên frontend, nên database thường ít khi đụng tới, nhưng chắc chắn những điều mình nói dưới đây sẽ bổ ích. Và mong được nhiều phản hồi góp ý.

Thiết kế database, hay cũng như thiết kế 1 phần mềm, một trang web, đều bắt đầu có quy trình gồm những bước cơ bản:

  • Phân tích yêu cầu.
  • Phác thảo ý tưởng ra giấy, làm bản mẫu.
  • Thực hiện.

Phân tích yêu cầu

Đây chắc hẳn là bước mà một lập trình viên chưa có nhiều kinh nghiệm (như mình chẳng hạn) ít chú tâm nhất. Không cần phải nói thêm về tầm quan trọng của giai đoạn này, khi đi làm được một thời gian bạn sẽ thấy code thực sự không khó, maintain và thay đổi theo những nhu cầu của khách hàng còn khó hơn gấp vạn lần. Bạn sẽ phải dần dần thay đổi tư duy. Lập trình viên không phải là đâm đầu vào code mà không cần biết chuyện gì đang xảy ra, hãy suy nghĩ như những product manager, hãy suy nghĩ như mình là người tạo ra sản phẩm đó.
Rồi, mở đầu với database, ở đây là MySQL, rất phổ biến, hầu như ai cũng xài, hầu như ai cũng nghĩ nó dễ, mà hầu như ai cũng không nắm hết về nó. Ở đây, mình không quan tâm bạn dùng giao diện hay command line, vì đằng nào cũng ra kết quả như nhau.

Phác thảo ý tưởng

Có thể bạn ung dung khi hiện tại có rất nhiều tool thiết kế database offline lẫn online, tuy nhiên, không gì thoải mái hơn công cụ truyền thống là bút chì và giấy. Hãy cầm lên và vẽ ra, bạn cần bao nhiêu bảng, liên kết với nhau như thế nào, liệu bảng nào nên tách ra riêng, bảng nào cần nhiều cột, bảng nào cần ít cột. Đây là giai đoạn tốn thời gian nhất. Hãy nghĩ ra tất cả các trường hợp có thể.

Thực hiện

Việc đầu tiên là tạo database, công việc có vẻ đơn giản, tuy nhiên sẽ có vài thứ cần chú ý. Điều đầu tiên đó chính là bạn phải xác định rõ ứng dụng của mình, nhu cầu đọc nhiều hơn hay là thêm sửa xóa nhiều hơn. Nếu đọc nhiều hơn, nên thiết kế ít bảng và có nhiều thông tin, nhiều cột hơn, nếu thêm/sửa/xóa là chủ yếu, hãy thiết kế nhiều bảng và trong mỗi bảng, dữ liệu được chuẩn hóa. Cái này phụ thuộc vào tư duy của người thiết kế.
Tiếp theo đó là charsetcollation, chúng luôn đi với nhau. Charset hiểu nôm na là tập hợp các ký tự (giống như bảng chữ cái) và dạng mã hóa của nó. Collation là tập hợp các quy tắc để so sánh các ký tự trong charset, thực chất là so sánh dạng đã mã hóa của nó. Tài liệu chính thống của MySQL đã nói rất rõ ở đây. Charset và collation cần được để tâm khi bạn làm database của những hệ thống đa ngôn ngữ, hoặc lưu những ký tự đặc biệt ví dụ như tiếng Việt. utf8 charset với utf8_general_ciutf8_unicode_ci collation đều làm tốt hai việc này. Và so sánh giữa hai loại collation này bạn có thể xem tại đây.

Xong, tiếp tới là tạo bảng. Cũng như việc tạo database, hầu hết chúng ta đều tạo với những thiết lập mặc định mà hệ thống làm cho, mà chẳng quan tâm gì những thiết lập đó có nghĩa là gì. Mình sẽ kể ra những thứ nên được chú tâm để thiết kế một database chuẩn, và dễ dàng tối ưu hết sức có thể. Đã đến lúc bạn để tâm tới cái gọi là storage engine của bảng. Trong kipalog cũng có 1 bài bàn về vấn đề này, bạn có thể xem ở đây. Mình chỉ bổ sung một chút cho dễ hiểu.
Với những mục đích thông thường, ta nên dùng InnoDB. Khi một dòng được thêm/sửa, thì MySQL sẽ chỉ khóa không cho những process khác thao tác với dòng đó, được gọi là row level lock, mọi thao tác với những dòng khác vẫn diễn ra bình thường, bởi vậy InnoDB có đặc tính gọi là Concurrency, vì các process khác không phải chờ khi dòng đó được hoàn tất. MyISAM thì chỉ hỗ trợ table level lock, bạn sẽ khắc hiểu là MySQL sẽ khóa toàn bộ bảng khi thao tác với 1 dòng, và sẽ không hợp lý khi ứng dụng của bạn cần hỗ trợ nhiều thao tác đồng thời. Memory engine hiện tại không được sử dụng nhiều, thay vào đó là Redis hay Memcached. Archive engine thích hợp để lưu log, tuy nhiên cách lưu log dùng bảng hay dùng file, và lưu thế nào sẽ là một bài toán khác.
Tiếp theo là tạo những cột cần thiết cho bảng, và điều cực kỳ quan trọng là kiểu dữ liệu, hãy sử dụng kiểu số nguyên khi có thể, kiểu ngày tháng thì nên dùng DATETIME ngoại trừ một vài field sử dụng TIMESTAMP để lưu lại thời điểm. Cụ thể:

  • Luôn luôn lưu một cột là người tạo để biết là ai tạo dòng này, một cột là ngày tạo, và ngày chỉnh sửa dòng này. Ngày tạo và ngày chỉnh sửa nên chọn kiểu dữ liệu là TIMESTAMP.
  • Đối với dữ liệu ngày tháng, nên lưu là DATETIME để phục vụ cho những nhu cầu sau này như đánh index, virtual column.
  • Tên cột càng ngắn càng tốt, dĩ nhiên phải rõ nghĩa và dễ hiểu.
  • Những cột ví dụ như "type", "status"... nên chọn kiểu là số nguyên, và hãy comment cho cột đó để biết những giá trị cột đó có thể mang, ví dụ 1:enabled, 2:disabled. Bạn đã bao giờ khóc thét khi không biết được 1 cột như vậy mang giá trị 3 mà không thể tìm được ở đâu cho biết rằng 3 có nghĩa là gì chưa?
  • Default value cho cột vẫn là một cuộc tranh luận, và bạn đừng nên tin ai cả, hãy đọc hết sức có thể và chỉ nên tin vào yêu cầu của chính mình. Một minh chứng cho những bình luận xem ai đúng ai sai như ở đây.
  • Hạn chế sử dụng kiểu dữ liệu là TEXT hết sức có thể.
  • Index rất quan trọng, hãy sử dụng khi có thể. Lời khuyên của mình: luôn luôn sử dụng index, đặc biệt những cột có kiểu dữ liệu là số nguyên. Cái cơ bản nhất, ai cũng biết đó là đánh index vào những cột nào xuất hiện trong điều kiện WHERE của câu truy vấn. Tuy nhiên, còn nhiều loại index khác cao cấp hơn, như covering index, merge index, hash index, index cho virtual column... Đánh index là cả một vấn đề, và nó là một cách để cải thiện tốc độ truy vấn hiệu quả nhất. Hãy thử nghĩ ra tất cả các trường hợp có thể, hãy nghĩ xem ví dụ một lúc nào đó bạn được yêu cầu tìm kiếm 1 user dựa vào email của user đó, bạn sẽ đánh index vào trường email với kiểu dữ liệu VARCHAR(50)?
  • Hãy học cách kiểm tra câu truy vấn của mình nhanh hay chậm, tiêu biểu là dùng lệnh EXPLAIN. Còn rất nhiều best practice về tạo database, các bạn sẽ học được trong quá trình mình làm. Hiện tại mình chỉ nhớ một vài tip nhỏ như này, có gì sẽ đóng góp thêm.

Cảm ơn các bạn đã đọc tới dòng này :)

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

ShinaBR2

11 bài viết.
98 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
62 16
Đây là một vấn đề kinh điển, và có rất nhiều bài viết về nó, tuy nhiên đa phần là dịch từ bản gốc ra và sao chép lại một vài câu lệnh, và câu hỏi t...
ShinaBR2 viết hơn 1 năm trước
62 16
White
35 10
Bàn về code thối Hãy tự đặt câu hỏi cho bạn, khi bắt đầu lập trình, bạn nghĩ tới điều gì? Đi phỏng vấn Điều đầu tiên tôi muốn nói về những câu hỏ...
ShinaBR2 viết 12 tháng trước
35 10
White
30 17
Single Page Applications, hay mình thường gọi là Single Page App SPA giờ đã trở nên quá đỗi quen thuộc và là một xu hướng của web. Vậy bạn đã thực ...
ShinaBR2 viết hơn 1 năm trước
30 17
Bài viết liên quan
White
21 0
Mysql innodb internal là một chủ đề khá sâu. Bản thân tôi cũng chưa bao quát hết. Bài viết này chỉ cung cấp một cái nhìn sơ lược. Để các bạn khôn...
manhdung viết hơn 3 năm trước
21 0
White
27 2
(Ảnh) Tiêu đề chỉ là câu khách :v, thực ra là có một vài điểm về mysql explain mà chắc chưa nhiều bạn biết, tớ cũng hay quên nên note lại cho nhớ ...
LinhPT viết 3 năm trước
27 2
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
11 bài viết.
98 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!