2016-02-14 15 views
11

Tôi đang tạo ứng dụng dành cho thiết bị di động Tôi sử dụng PHP & MySQL để viết một chương trình phụ trợ - REST API.Làm thế nào để lưu trữ 60 Booleans trong một cơ sở dữ liệu MySQL?

Nếu tôi phải lưu trữ khoảng 50-60 giá trị Boolean trong bảng có tên "Báo cáo" (người dùng phải kiểm tra mọi thứ trong biểu mẫu) trong ứng dụng di động của tôi, tôi lưu giá trị (0/1) trong một mảng đơn giản. Trong MySql Table của tôi tôi nên tạo một cột khác nhau cho mỗi giá trị Boolean hoặc là nó đủ nếu tôi chỉ đơn giản là sử dụng một chuỗi hoặc một Int để lưu trữ nó như là một "số" như "110101110110111 ..."?

Tôi lấy và đặt dữ liệu bằng JSON.

CẬP NHẬT 1: Tất cả những gì tôi phải làm là kiểm tra nếu mọi thứ là 1, nếu một trong số đó là 0 thì đó là "sự cố". Trong 2 năm, bảng này sẽ có khoảng 15.000-20.000 hàng, nó phải rất nhanh và tiết kiệm không gian càng tốt.

CẬP NHẬT 2: Xét về tốc độ giải pháp nào nhanh hơn? Tạo các cột riêng biệt và lưu trữ nó trong một chuỗi/kiểu nhị phân. Nếu tôi phải kiểm tra xem cái nào là 0? Đó có phải là giải pháp tuyệt vời nếu tôi lưu trữ nó dưới dạng "số" trong một cột và nếu không phải là "111..111" thì gửi nó đến ứng dụng dành cho thiết bị di động dưới dạng JSON nơi tôi phân tích giá trị và phân tích giá trị trên thiết bị của người dùng? Hãy nói rằng tôi phải đối phó với 50K hàng.

Xin cảm ơn trước.

+2

Nếu bạn cần tìm kiếm (sử dụng các công cụ như 'WHERE bool_a AND NOT bool_b') trên các giá trị của những lá cờ này, điều đó sẽ đẩy bạn lưu chúng vào cột riêng của chúng. Nhưng bạn chưa cho chúng tôi biết ứng dụng của bạn cần sử dụng dữ liệu này như thế nào. –

+0

Bạn nói đúng. Tất cả những gì tôi phải làm là kiểm tra nếu mọi thứ là 1, nếu một trong số đó là 0 thì đó là một "vấn đề". Trong 2 năm, bảng này sẽ có khoảng 15.000-20.000 hàng, nó phải rất nhanh và tiết kiệm không gian càng tốt. – nethuszar

+0

Bạn có thể đi với cờ, nếu bạn là một trăm phần trăm chắc chắn bạn không cần phải thêm công cụ ở giữa. Bạn có thể sử dụng kiểu BINARY cho điều đó. – MartijnK

Trả lời

13

Cột riêng cho mỗi giá trị linh hoạt hơn khi tìm kiếm.

Bảng khóa/giá trị riêng biệt linh hoạt hơn nếu các hàng khác nhau có các tập hợp giá trị Boolean khác nhau.

Và, nếu

  1. danh sách các giá trị Boolean là nhiều hay ít tĩnh
  2. tất cả các hàng của bạn có tất cả những giá trị Boolean
  3. tìm kiếm hiệu suất quan trọng của bạn là tìm hàng trong đó bất kỳ giá trị nào là false

thì sử dụng chuỗi văn bản như '1001010010' vv là cách tốt để lưu trữ chúng. Bạn có thể tìm kiếm như thế này

WHERE flags <> '11111111' 

để tìm các hàng bạn cần.

Bạn có thể sử dụng cột BINARY với một bit cho mỗi cờ. Nhưng bảng của bạn sẽ dễ sử dụng hơn cho các truy vấn bình thường và kiểm tra nhãn cầu nếu bạn sử dụng văn bản. Tiết kiệm không gian từ việc sử dụng BINARY thay vì CHAR sẽ không đáng kể cho đến khi bạn bắt đầu lưu trữ hàng triệu hàng.

chỉnh sửa Có thể nói: mỗi khi tôi xây dựng một cái gì đó như thế này với mảng thuộc tính Boolean, sau này tôi đã thất vọng về mức độ linh hoạt của nó. Ví dụ, giả sử nó là một danh mục các bóng đèn. Tại thời điểm chuyển giao thiên niên kỷ, những lá cờ Boolean có thể đã được những thứ như thế

screw base 
halogen 
mercury vapor 
low voltage 

Sau đó, mọi thứ thay đổi và tôi thấy mình cần nhiều cờ Boolean, như,

LED 
CFL 
dimmable 
Energy Star 

vv Tất cả của một đột ngột các kiểu dữ liệu của tôi không đủ lớn để giữ những gì tôi cần chúng giữ lại.Khi tôi viết "danh sách các giá trị Boolean của bạn có nhiều hay ít tĩnh" Tôi có nghĩa là bạn không mong đợi một cách hợp lý để có một cái gì đó giống như các đặc tính của bóng đèn thay đổi trong suốt thời gian tồn tại của ứng dụng của bạn.

Vì vậy, một bảng thuộc tính riêng biệt có thể là là giải pháp tốt hơn. Nó sẽ có các cột sau:

item_id   fk to item table   -- pk 
    attribute_id  attribute identifier  -- pk 
    attribute_value 

Điều này cuối cùng là linh hoạt. Bạn chỉ có thể thêm cờ mới. Bạn có thể thêm chúng vào các mục hiện có hoặc vào các mục mới, bất kỳ lúc nào trong thời gian tồn tại của ứng dụng của bạn. Và, mỗi mục không cần cùng một bộ sưu tập cờ. Bạn có thể viết "những mục nào có bất kỳ thuộc tính sai nào?" truy vấn như sau:

SELECT DISTINCT item_id FROM attribute_table WHERE attribute_value = 0 

Nhưng, bạn phải cẩn thận vì truy vấn "những mục nào thiếu thuộc tính" khó viết hơn nhiều.

+0

Điều gì về BIT (N) thay vì chuỗi? –

+0

Cảm ơn bạn đã trả lời. "mỗi khi tôi xây dựng một cái gì đó như thế này với mảng các thuộc tính Boolean, sau này tôi đã thất vọng" Bạn có thể cho tôi giải pháp tốt hơn không? Tôi mở để học những điều mới. – nethuszar

+0

Chắc chắn là một cái bàn mới, nó cũng được chuẩn hóa. https://en.wikipedia.org/wiki/Database_normalization#Minimize_redesign_when_extending_the_database_structure –

11

Vì mục đích cụ thể của bạn, khi bất kỳ cờ 0 nào là problen (ngoại lệ) và hầu hết các mục nhập (như 99%) sẽ là "1111 ... 1111", tôi không thấy lý do nào để lưu trữ tất cả. Tôi thà tạo ra một bảng riêng biệt chỉ lưu trữ các cờ không được kiểm soát. Bảng có thể trông giống như: uncheked_flags (user_id, flag_id). Trong một bảng khác, bạn lưu trữ các định nghĩa cờ của mình: cờ (flag_id, flag_name, flag_description).

Sau đó, báo cáo của bạn đơn giản như SELECT * FROM unchecked_flags.

Cập nhật - có thể định nghĩa bảng:

CREATE TABLE `flags` (
    `flag_id` TINYINT(3) UNSIGNED NOT NULL AUTO_INCREMENT, 
    `flag_name` VARCHAR(63) NOT NULL, 
    `flag_description` TEXT NOT NULL, 
    PRIMARY KEY (`flag_id`), 
    UNIQUE INDEX `flag_name` (`flag_name`) 
) ENGINE=InnoDB; 

CREATE TABLE `uncheked_flags` (
    `user_id` MEDIUMINT(8) UNSIGNED NOT NULL, 
    `flag_id` TINYINT(3) UNSIGNED NOT NULL, 
    PRIMARY KEY (`user_id`, `flag_id`), 
    INDEX `flag_id` (`flag_id`), 
    CONSTRAINT `FK_uncheked_flags_flags` FOREIGN KEY (`flag_id`) REFERENCES `flags` (`flag_id`), 
    CONSTRAINT `FK_uncheked_flags_users` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) 
) ENGINE=InnoDB; 
1

Bạn thể có được một tìm kiếm tốt hơn ra của việc sử dụng cột chuyên dụng, cho mỗi boolean, nhưng cardinality là nghèo và thậm chí nếu bạn chỉ số mỗi cột nó sẽ liên quan đến một chút công bằng của traversal hoặc quét.

Nếu bạn chỉ tìm kiếm GIÁ TRỊ CAO 0xFFF .... thì chắc chắn bitmap, điều này giải quyết vấn đề cardinality của bạn (mỗi bản cập nhật OP). Nó không giống như bạn đang kiểm tra chẵn lẻ ... Cây tuy nhiên sẽ được nặng nề nghiêng đến HIGH-GIÁ TRỊ nếu điều này là bình thường và có thể tạo ra một điểm nóng dễ bị nút chia tách khi chèn.

Ánh xạ bit và sử dụng mặt nạ bitwise sẽ tiết kiệm dung lượng nhưng sẽ cần phải căn chỉnh với byte để có thể có "mẹo" chưa sử dụng (cung cấp cho các trường trong tương lai), vì vậy mặt nạ phải dài hoặc trường đệm với 1s.

Nó cũng sẽ thêm tính phức tạp vào kiến ​​trúc của bạn, có thể yêu cầu mã hóa riêng biệt, tiêu chuẩn riêng biệt.

Bạn cần thực hiện phân tích về tầm quan trọng của bất kỳ tìm kiếm nào (bạn có thể không thường xuyên tìm kiếm tất cả. Hoặc thậm chí bất kỳ trường riêng biệt nào).

Đây là chiến lược rất phổ biến cho dữ liệu không chuẩn hóa và cũng có thể yêu cầu dịch vụ điều chỉnh cho các khách hàng cụ thể. (Trường hợp một số reponses được fatter hơn những người khác cho cùng một giao dịch).

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