2009-09-18 74 views
15

Tôi có một số đối tượng khác nhau với số thuộc tính khác nhau. Cho đến bây giờ, tôi đã lưu dữ liệu trong các tệp XML dễ dàng cho phép thay đổi số lượng thuộc tính. Nhưng tôi đang cố gắng chuyển nó vào cơ sở dữ liệu.Cách lưu trữ dữ liệu với số lượng thuộc tính động trong cơ sở dữ liệu

Cách ưa thích của bạn để lưu trữ dữ liệu này là gì?

Một vài chiến lược tôi đã xác định được cho đến nay:

  • Có một trường duy nhất có tên là "thuộc tính" trong bảng của đối tượng và lưu trữ dữ liệu tuần tự hoặc json'ed trong đó.
  • Lưu trữ dữ liệu trong hai bảng (đối tượng, thuộc tính) và sử dụng một phần ba để lưu các mối quan hệ, làm cho nó thành một mối quan hệ n: m thực. Giải pháp rất sạch sẽ, nhưng có thể rất tốn kém để lấy toàn bộ đối tượng và tất cả các thuộc tính của nó
  • Xác định các thuộc tính mà tất cả các đối tượng có điểm chung và tạo trường cho các đối tượng này vào bảng của đối tượng. Lưu trữ các thuộc tính còn lại dưới dạng dữ liệu tuần tự trong một trường khác. Điều này có lợi thế so với chiến lược đầu tiên, giúp việc tìm kiếm dễ dàng hơn.

Bất kỳ ý tưởng nào?

+0

Động lực để chuyển sang giải pháp db là gì? Bạn nói dưới đây, tốc độ đó là mối quan tâm chính của bạn. Bạn có nghĩ rằng giải pháp db sẽ nhanh hơn phương pháp XML hiện tại của bạn không? –

+0

Một chiến lược thứ tư đến với tâm trí với DVK đề xuất như nhau: Lưu trữ các thuộc tính phổ biến trong bảng đối tượng và lưu trữ tất cả các khác bằng cách sử dụng một mối quan hệ 1: n một bảng thứ hai. Có vẻ như thỏa hiệp tốt nhất cho tốc độ, tính linh hoạt và giải pháp sạch (@Tobiask) –

+0

@Corey, không, tôi không biết. Các giải pháp XML là đáng kinh ngạc nhanh vào lúc này và tôi không nghĩ rằng một DB có thể theo kịp với điều đó. Nó là một tập thể dục của tôi, cố gắng làm cho hệ thống linh hoạt hơn liên quan đến các tùy chọn lưu trữ và đồng thời cải thiện các kỹ năng MySQL của tôi. –

Trả lời

18

Nếu bạn bao giờ kế hoạch tìm kiếm attribtes cụ thể, đó là một ý tưởng tồi để tuần tự hóa chúng thành một cột duy nhất, vì bạn sẽ phải sử dụng các hàm mỗi hàng để lấy thông tin ra - điều này không bao giờ được cân tốt.

Tôi sẽ chọn lựa lựa chọn thứ hai của bạn. Có một danh sách các thuộc tính trong một bảng thuộc tính, các đối tượng trong bảng riêng của chúng và một bảng mối quan hệ nhiều-nhiều được gọi là các thuộc tính đối tượng.

Ví dụ:

objects: 
    object_id integer 
    object_name varchar(20) 
    primary key (object_id) 
attributes: 
    attr_id  integer 
    attr_name varchar(20) 
    primary key (attr_id) 
object_attributes: 
    object_id integer references (objects.object_id) 
    attr_id  integer references (attributes.attr_id) 
    primary key (object_id,attr_id) 

mối quan tâm của bạn về hiệu suất được ghi nhận, nhưng trong kinh nghiệm của tôi, nó luôn luôn tốn kém hơn để chia một cột hơn để kết hợp nhiều cột. Nếu nó chỉ ra rằng có vấn đề hiệu suất, nó hoàn toàn chấp nhận được để phá vỡ 3NF vì lý do hiệu suất.

Trong trường hợp đó, tôi sẽ lưu trữ theo cách tương tự nhưng cũng có cột có dữ liệu được tuần tự hóa thô. Miễn là bạn sử dụng trình kích hoạt chèn/cập nhật để giữ cho dữ liệu cột và kết hợp được đồng bộ hóa, bạn sẽ không gặp bất kỳ sự cố nào. Nhưng bạn không nên lo lắng về điều đó cho đến khi một vấn đề thực sự bề mặt.

Bằng cách sử dụng các trình kích hoạt đó, bạn sẽ giảm thiểu công việc cần thiết chỉ khi dữ liệu thay đổi. Bằng cách cố gắng trích xuất thông tin cột phụ, bạn thực hiện công việc không cần thiết trên mọi lựa chọn.

+0

Chính xác mối quan tâm của tôi với chiến lược đầu tiên. –

+0

câu hỏi là tốt hơn cho hiệu suất phương pháp của bạn là eav ý kiến ​​của bạn về mô hình json lưu trữ dữ liệu –

+0

@babakfaghihian, tôi nghĩ rằng tôi bao gồm rằng trong hai đoạn cuối cùng của tôi, có? Không thể phá vỡ 3NF cho hiệu suất miễn là bạn hiểu và giảm thiểu rủi ro (của các yếu tố dữ liệu "không đồng ý" với nhau). Lưu trữ dữ liệu gốc (XML, JSON hoặc bất kỳ thứ gì) là một cách tiếp cận này. – paxdiablo

1

có vẻ như bạn cần một cái gì đó liếm couchdb, không phải là RDBMS.

+0

Điều đó nghe có vẻ giống như một giải pháp lý tưởng. Thật không may tôi chủ yếu là đối phó với các kịch bản mà tôi không có một possiblity để sử dụng nhiều hơn MySQL, hãy để một mình cài đặt một DB trên máy chủ. –

6

Một biến thể của giải pháp 2ngày của bạn chỉ là hai bảng (giả sử tất cả các thuộc tính của một loại duy nhất):

T1: | cột dữ liệu Object | object_id |

T2: | Id đối tượng | attribute_name | giá trị thuộc tính | (chỉ mục duy nhất trên 2 cột đầu tiên)

Điều này thậm chí còn hiệu quả hơn khi được kết hợp với giải pháp thứ 3, ví dụ: tất cả các trường phổ biến đều đi vào T1.

Sstuffing> 1 thuộc tính vào blob cùng là không khuyến khích - bạn không thể lọc theo thuộc tính, bạn có thể không có hiệu quả cập nhật chúng

+0

Thực ra, đó là chính xác những gì tôi nghĩ sau khi đọc qua ba chiến lược của tôi một lần nữa. Âm thanh như cách tốt nhất để đi. –

+1

Xin chào. Đây được gọi là bảng Thuộc tính-Giá trị-Thuộc tính và thiết kế kém là http://programmers.stackexchange.com/questions/93124/eav-is-it-really-bad-in-all-scenarios –

+0

@GabriBotha - các câu trả lời trên câu hỏi được liên kết không có cách nào hỗ trợ khẳng định căn hộ và không tự tin của bạn rằng đó là một thiết kế "xấu". Đó là một thiết kế với những sai sót cụ thể - như TẤT CẢ các thiết kế - và các tình huống cụ thể, đó là cách tiếp cận tốt nhất. – DVK

1

nếu bạn định chỉnh sửa/thao tác/xóa thuộc tính ở thời điểm sau này, hãy thực hiện đúng n: m (tùy chọn thứ hai) sẽ là thứ tôi truy cập. (Hoặc cố gắng làm cho nó 2 bảng mà cùng một thuộc tính lặp đi lặp lại.Nhưng kích thước dữ liệu sẽ cao)

Nếu bạn không giao dịch với các thuộc tính (chỉ chụp và hiển thị dữ liệu) thì bạn có thể tiếp tục và lưu trữ trong một trường với một số dấu phân cách (Hãy chắc chắn rằng dấu tách sẽ không xuất hiện trong giá trị thuộc tính)

1

Nếu bạn đang sử dụng một db quan hệ, thì tôi nghĩ bạn đã làm tốt việc liệt kê các tùy chọn. Họ từng có ưu và khuyết điểm của họ. Bạn đang ở vị trí tốt nhất để quyết định điều gì làm việc tốt nhất cho hoàn cảnh của bạn.

Cách tiếp cận được tuần tự hóa có thể là nhanh nhất (tùy thuộc vào mã của bạn để hủy tuần tự hóa), nhưng điều đó có nghĩa là bạn sẽ không thể truy vấn dữ liệu bằng SQL. Nếu bạn nói rằng bạn không cần phải truy vấn dữ liệu với SQL, thì tôi đồng ý với @ longneck, có lẽ bạn nên sử dụng một db kiểu khóa/giá trị thay vì một db quan hệ.

EDIT - đọc thêm nhận xét của bạn, TẠI SAO bạn chuyển sang db nếu tốc độ là mối quan tâm chính của bạn. BAD về triển khai XML hiện tại của bạn là gì?

2

tôi đã sử dụng để thực hiện this scheme:

t_class (id RAW(16), parent RAW(16)) -- holds class hierachy. 
t_property (class RAW(16), property VARCHAR) -- holds class members. 
t_declaration (id RAW(16), class RAW(16)) -- hold GUIDs and types of all class instances 
t_instance (id RAW(16), class RAW(16), property VARCHAR2(100), textvalue VARCHAR2(200), intvalue INT, doublevalue DOUBLE, datevalue DATE) -- holds 'common' properties 

t_class1 (id RAW(16), amount DOUBLE, source RAW(16), destination RAW(16)) -- holds 'fast' properties for class1. 
t_class2 (id RAW(16), comment VARCHAR2(200)) -- holds 'fast' properties for class2 
--- etc. 

RAW(16) là nơi Oracle giữ GUID s

Nếu bạn muốn chọn tất cả các thuộc tính cho một đối tượng, bạn phát hành:

SELECT i.* 
FROM (
     SELECT id 
     FROM t_class 
     START WITH 
       id = (SELECT class FROM t_declaration WHERE id = :object_id) 
     CONNECT BY 
       parent = PRIOR id 
     ) c 
JOIN property p 
ON  p.class = c.id 
LEFT JOIN 
     t_instance i 
ON  i.id = :object_id 
     AND i.class = p.class 
     AND i.property = p.property 

t_property giữ nội dung bạn thường không tìm kiếm (như, mô tả văn bản, v.v.)

Thuộc tính nhanh là các bảng thông thường bạn có trong cơ sở dữ liệu, để làm cho các truy vấn hiệu quả. Chúng giữ giá trị chỉ cho các trường hợp của một lớp nhất định hoặc con cháu của nó. Điều này là để tránh tham gia thêm.

Bạn không phải sử dụng bảng nhanh và giới hạn tất cả dữ liệu của mình vào bốn bảng này.

+1

Chà, thậm chí còn hơn một bước nữa. Nhưng điều đó sẽ không dẫn đến một số lượng lớn các bảng nếu bạn có một bảng cho mỗi loại lớp? Và câu lệnh SQL cuối cùng của bạn thực sự làm cho tôi hy vọng cuốn sách MySQL mà tôi đã sắp xếp sẽ đến sớm hơn là sau .. –

+1

'@ Jörg': đây là trong 'Oracle' và đây là cú pháp' Oracle'. Trong 'MySQL', bạn sẽ cần triển khai hàm này theo một cách khác: http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/ – Quassnoi

+0

Bạn chỉ cần tạo bảng cho" thuộc tính nhanh ": khi bạn cần tạo chỉ mục tổng hợp trên hai hoặc nhiều thuộc tính. Nếu không, bạn chỉ có thể có các bảng cơ bản '4'. – Quassnoi

3

Hãy để tôi nói một cách cụ thể những gì DVK đang nói.

giá trị Giả sử là của cùng một loại bảng sẽ trông giống như (chúc may mắn, tôi cảm thấy bạn sẽ cần đến nó):

 
dynamic_attribute_table 
------------------------ 
id   NUMBER 
key  VARCHAR 
value  SOMETYPE? 

dụ (xe ô tô):

 
|id| key | value | 
--------------------------- 
| 1|'Make' |'Ford'  | 
| 1|'Model' |'Edge'  | 
| 1|'Color' |'Blue'  | 
| 2|'Make' |'Chevrolet'| 
| 2|'Model' |'Malibu' | 
| 2|'MaxSpeed'|'110mph' | 

Vì vậy ,
thực thể 1 = {('Làm', 'Ford'), ('Mẫu', 'Cạnh'), ('Màu', 'Xanh')}
và,
pháp nhân 2 = {('Tạo ',' Chevrolet '), (' Mẫu ',' Malibu '), (' MaxSpeed ​​',' 110mph ')}.

+0

nếu bạn muốn nói máy có màu đen và màu vàng? –

Các vấn đề liên quan