Khi bạn bắt đầu nhận được "các trường do người dùng xác định" như thường thấy trong trình theo dõi lỗi, quản lý tài nguyên khách hàng và các công cụ kinh doanh tương tự là chúng không được hỗ trợ với một bảng có các trường bajillion (nếu có, thì đó có thể là vấn đề của của riêng nó).
Thay vào đó, những gì bạn tìm thấy là các thiết kế bảng Giá trị thuộc tính thực thể và công cụ quản trị được liên kết để quản lý các thuộc tính hợp lệ.
Hãy xem xét bảng sau:
+ -------------- +
| điều |
| -------------- |
| id |
| loại |
| giải thích |
| attr1 |
| attr2 |
| attr3 |
| attr4 |
| attr5 |
+ -------------- +
Đây là sau khi bạn đã thêm một vài thuộc tính. Thay vì attr1
giả vờ nó đọc artist
hoặc tracks
hoặc genre
hoặc bất cứ điều gì thuộc tính điều có. Và thay vì 5, nếu nó là 50. Rõ ràng là không thể quản lý được. Nó cũng yêu cầu cập nhật mô hình và triển khai lại ứng dụng để xử lý một lĩnh vực mới. Không lý tưởng.
Bây giờ hãy xem xét cấu trúc bảng sau:
+ -------------- + + --------------- + + ------------- +
| điều | | điều_attr | | attr |
| -------------- | | --------------- | | ------------- |
| id | <--- + | điều_id (fk) | +> | id |
| loại | | attr_id (fk) | + - + | tên |
| giải thích | | giá trị | | |
+ -------------- + + --------------- + + ------------- +
Bạn đã có điều của bạn với các lĩnh vực cơ bản của nó. Bạn có thêm hai bảng. Một với các thuộc tính. Mỗi lĩnh vực là một hàng trong attr
bảng. Và sau đó là thing_attr
một cặp khóa ngoại liên quan đến thing
bảng và attr
bảng. Và điều này sau đó có một trường giá trị nơi bạn lưu trữ bất cứ giá trị nào của trường cho thực thể đó.
Và bây giờ bạn đã có một cấu trúc trong đó bảng attr có thể được cập nhật trong thời gian chạy và các trường mới có thể được thêm (hoặc xóa) một cách nhanh chóng mà không ảnh hưởng đáng kể đến ứng dụng tổng thể.
Các truy vấn phức tạp hơn một chút và xác thực cũng trở nên phức tạp hơn (cả thủ tục lưu trữ sôi nổi hoặc tất cả các phía máy khách). Đó là một sự đánh đổi trong thiết kế.
Cũng xem xét tình huống một ngày nào đó bạn cần thực hiện di chuyển và bạn quay lại ứng dụng để thấy rằng hiện tại có hơn một nửa tá hoặc nhiều hơn các thuộc tính so với lược đồ bạn đã phân phối ban đầu. Điều này làm cho việc di chuyển và nâng cấp xấu trong đó bảng Giá trị thuộc tính thực thể, khi được sử dụng đúng cách, có thể sạch hơn. (Không phải luôn luôn, nhưng có thể.)
Có bất kỳ nhược điểm nào khi chỉ sửa đổi lược đồ khi chạy không? Nếu người dùng nghĩ rằng một thứ cần một thuộc tính mới, chỉ cần tự động thêm một cột vào bảng?
Nếu bạn đang làm việc với hương vị thích hợp của cơ sở dữ liệu nosql, có lẽ bạn có thể làm điều này (lưu ý rằng hương vị thích hợp của nosql cho điều này có thể sẽ là một kho lưu trữ khóa-giá trị , đó là bảng EAV cho các mối quan hệ được mô tả ở trên) không có quá nhiều rắc rối Tuy nhiên, nó đi kèm với tất cả các thỏa hiệp cho nosql được mô tả ở nơi khác rất chi tiết.
Nếu bạn đang làm việc trên một cơ sở dữ liệu quan hệ - bạn cần phải có lược đồ. Thêm cột một cách linh hoạt có nghĩa là một số tập hợp con của những điều sau đây là đúng:
- Bạn đang làm lập trình siêu cơ sở dữ liệu. Thay vì có thể ánh xạ sạch cột này sang trường đó bằng một ORM đẹp mắt, có lẽ bạn đang làm những việc như thế
select *
và sau đó thực hiện một số mã phức tạp để tìm hiểu dữ liệu thực sự là gì (xem Kết quả của Java SetMetaData ) và sau đó lưu trữ nó trong bản đồ ( hoặc một số kiểu dữ liệu khác - nhưng các trường không đẹp trong mã). Điều này sau đó sẽ loại bỏ một chút an toàn về loại và lỗi đánh máy mà bạn có với cách tiếp cận truyền thống.
- Bạn có thể đã từ bỏ ORM. Điều này có nghĩa là bạn đang viết sql thô cho tất cả các mã thay vì để hệ thống thực hiện công việc cho bạn.
- Bạn đã từ bỏ việc nâng cấp sạch sẽ. Điều gì xảy ra khi khách hàng thêm một trường có một tên mà phiên bản tiếp theo của bạn cũng sử dụng? Trong trang web mai mối, bản nâng cấp muốn thêm
hasdate
trường để lưu dấu thời gian đã được xác định như hasdate
với boolean cho một trận đấu thành công ... và việc nâng cấp của bạn bị phá vỡ.
- Bạn tin tưởng rằng khách hàng không phá vỡ hệ thống bằng cách sử dụng một số từ dành riêng cũng phá vỡ các truy vấn của bạn ... ở đâu đó.
- Bạn đã ràng buộc mình với một thương hiệu cơ sở dữ liệu. Các DDL của cơ sở dữ liệu khác nhau là khác nhau. Các loại cơ sở dữ liệu là ví dụ dễ nhất về điều này.
varchar2
vs text
và tương tự. Mã của bạn để thêm cột sẽ hoạt động trên MySQL nhưng không phải Postgres hoặc Oracle hoặc SQL Server.
- Bạn có tin tưởng khách hàng để thực sự thêm dữ liệu tốt ? Chắc chắn, EAV không còn lý tưởng nhưng bây giờ bạn đã có một số tên bảng tối nghĩa khủng khiếp mà nhà phát triển không thêm, với loại chỉ mục sai (nếu có), không có ràng buộc nào được thêm vào mã khi cần được và như vậy.
- Bạn đã trao đặc quyền sửa đổi lược đồ cho người dùng đang chạy ứng dụng. Các bảng thả nhỏ Bobby không thể thực hiện được khi bạn bị hạn chế đối với SQL thay vì DDL (chắc chắn bạn có thể thực hiện
delete * from students
thay thế, nhưng bạn thực sự không thể làm xáo trộn cơ sở dữ liệu theo những cách xấu). Số lượng điều có thể sai với truy cập lược đồ hoặc từ một vụ tai nạn hoặc hoạt động độc hại trên bầu trời.
Điều này thực sự sôi sục đến "đừng làm điều đó." Nếu bạn thực sự muốn điều này, hãy đi với một mẫu đã biết của cấu trúc bảng EAV hoặc cơ sở dữ liệu hoàn toàn dành riêng cho cấu trúc này. Đừng để mọi người tạo các trường tùy ý trong một bảng. Những cơn đau đầu chỉ là không đáng.