Hướng dẫn mysql data structure - cấu trúc dữ liệu mysql
Thiết kế tốt về cả logic lẫn physic là những cột mốc quan trọng đem tới hiệu năng cao, và bạn phải thiết kế schema của mình theo những câu query mà bạn sẽ chạy. Điều này thường dẫn đến việc trao đổi được mất. Ví dụ như denormalized schema có thể tăng tốc một số loại query nhưng lại làm những loại khác chậm đi. Thêm vào bảng counter và summary là một cách hay để tối ưu query, nhưng chúng gây khó khăn khi maintain. Những tính năng của MySQL bị ảnh hưởng một chút từ suy nghĩ trên. Chapter này và chapter tiếp theo sẽ tập chung vào đánh index, xem xét một chút về schema design. Chúng tôi cho rằng bạn đã biết về design database, nên đây không phải là chapter để giới thiệu, hay là chapter nâng cao. Đây là chapter về MySQL database design. Chapter này là sự chuẩn bị cho 2 chapter kế tiếp. Trong 3 chapter, chúng ta sẽ tìm hiểu sự tương tác của logical design, physical design và query execution. Điều này yêu cầu cả sự hiểu biết toàn cảnh lẫn các chi tiết bên trong. Bạn cần hiều được toàn bộ system để có thể biết được làm sao các phần nhỏ tương tác với nhau. Bạn có thể thấy nó có ích khi đọc chapter này trước sau đó bước vào chapter index, query optimaztion. Rất nhiều phần thảo luận có liên hệ với nhau cho nên hãy đọc hết. **Choosing Optimal Data Types **
WHOLE NUMBER: Có 2 kiểu của number whole number và real number. Nếu dùng số nguyên có thể dùng: tinyint, smallint, medinumint, int, hoặc bigint yêu cầu 8, 16, 24, 32 và 64 bit lưu trữ. Số nguyên còn có option usigned. MySQL để bạn định nghĩa độ dài của integer như int(11) nhưng nó k có ý nghĩa gì trong hầu hết ứng dụng. Nó không hạn chế range of value, chỉ hiển thị ra 11 chữ số. Mặc dù khai báo là int(1) nhưng nó có thể chứa đc = int(20): Có 2 kiểu của number whole number và real number. Nếu dùng số nguyên có thể dùng: tinyint, smallint, medinumint, int, hoặc bigint yêu cầu 8, 16, 24, 32 và 64 bit lưu trữ. Số nguyên còn có option usigned. MySQL để bạn định nghĩa độ dài của integer như int(11) nhưng nó k có ý nghĩa gì trong hầu hết ứng dụng. Nó không hạn chế range of value, chỉ hiển thị ra 11 chữ số. Mặc dù khai báo là int(1) nhưng nó có thể chứa đc = int(20) **REAL NUMBER: ** Dành cho kiểu có phần thực, nhưng vẫn dùng cho kiểu nguyên đc. FLOAT và DOUBLE hộ trợ tính toán ~ với dấu , động. Kiểu DECIMAL hỗ trợ tính toán chính xác phần phân số. Cả 2 kiểu , động và DECIMAL đều có thể qui định độ chính xác. STRING TYPE: VARCHAR & CHAR
Tips:
Trong trường hợp này nên sử dụng foreign key hoặc lookup table. Nếu bạn muốn thêm một new country thì k có cách nào khác ngoài sử dụng alter table. Và trong MySQL 5.0 trở lên, bạn muốn thêm một phần tử vào vị trí nào đi nữa thì nó vẫn ở cuối list. Thỉnh thoảng enum dễ gây nhầm lẫn với set. Ví dụ:
Trong trường hợp này nên sử dụng ENUM thay vì SET. Vì ENUM chỉ cho phép chứa 1 trong 2 giá trị còn SET cho phép chứa 1 -> nhiều giá trị.
Chúng tôi đã viết từ trước về việc tránh sử dung NULL, và thật lòng chúng tôi đề nghị bạn sử dụng một cách khác khi vẫn có thể. Kể cả khi bạn muốn lưu trữ một giá trị “k có giá trị”, bạn cũng k nên dùng null. Có thể sử dụng số 0 hoặc 1 giá trị qui ước trước hoặc một empty string. Nhưng trong một số trường hợp sử dụng NULL là tốt hơn và làm cho code đỡ rắc rối hơn tuy NULL là một lỗi rất khó tránh nhưng nó có thể còn là một cách làm tốt hơn những cái khác. Như đã nhắc từ trước, MySQL có đánh index cho NULL nhưng Oracle thì không.
Để thực hiện câu query này, MySQL cần scan published index của message table. Mỗi row nó tìm được, nó sẽ thăm dò trong table user và check xem user đó có là premium không. Cách này chỉ hiệu quả khi số lượng nhỏ của user là premium. Một câu query khác sẽ bắt đầu từ table user, select premium user và lấy ra tất cả message sau đó sort. Trường hợp này còn tệ hơn. Vấn đề nằm ở chỗ join, nó làm cả 2 việc là sort và filter nhưng chỉ với 1 index. Nếu bạn denormalize data bằng cạch gộp nhiều bảng và đánh index với (account_type, publised), bạn sẽ k cần join và hiệu quả hơn nhiều:
A Mixture of Normalized and Denormalized Cả normalized và denormalized đều có ưu và nhược. Làm sao chọn được cái nào là best design? Sự thật là, fully normalized và fully denormalized schema giống như những con chuột thí nghiệm: chúng thường không có í nghĩa gì ngoài thể giới bên ngoài. Trong thế giới bên ngoài bạn thường kết hợp 2 cách tiếp cận, sử dụng một phần nào đó là normalized, cache table,... Trong ví dụ trên, thực tế thay vì denormalizing fully table thì có thể lưu account_type trên cả bảng user và message. Điều này tránh vấn đề insert và delete bị mất toàn bộ dữ liệu. Bạn sẽ vẫn lưu lại được user mặc dù đã xóa hết message. Nó không làm bảng user, message lớn hơn quá nhiều nhưng giúp bạn select hiệu quả. Tuy nhiên, bây giờ update user lại khó khăn hơn bởi vì phải thay đổi trên cả 2 table. Để xem xét nó có là vấn đề thực sự hay không bạn phải tính toán tần suất thực hiện việc thay đổi có nhiều không và thời gian để hoàn thành thay đổi và so sánh với thời gian thực hiện câu lệnh select. Một ví dụ hay khác để chuyển từ parent table -> child table là dùng để sort. Nếu với normalized schema thì thật là tốn nhiều thời gian để sort message theo author’s name nhưng denormalized schema thì nhanh hơn rất nhiều nều cache và đánh index author_name trong bảng message. (Chương 4 - Hiệu suất cao MySQL, Phiên bản thứ 3) (tobecontinue) |