2013-06-06 47 views
7

Tôi có một bảng gọi là events nơi tất cả thông tin mới đều được gửi đi. Bảng này hoạt động như một tham chiếu cho tất cả truy vấn cho (các) nguồn cấp dữ liệu tin tức để các mục sự kiện được chọn từ đó và thông tin tương ứng với sự kiện đó được truy xuất từ ​​các bảng chính xác.Làm thế nào để có ID duy nhất trên hai hoặc nhiều bảng trong MySQL?

Bây giờ, đây là vấn đề của tôi. Tôi có E_ID trong bảng sự kiện tương ứng với ID của một sự kiện trong một bảng khác, có thể là T_ID cho tracks, S_ID cho status và cứ thế ... Những ID này có thể giống nhau trong thời gian này sử dụng một giá trị auto_increment khác nhau cho mỗi bảng để status bắt đầu trên 500 tracks trên 0 vv Rõ ràng, tôi không muốn làm điều đó vì tôi không có ý tưởng nào trong đó bảng sẽ có nhiều dữ liệu nhất trong đó. Tôi giả định status sẽ nhanh chóng vượt quá tracks.

Thông tin được đưa vào bảng event có trình kích hoạt. Đây là một ví dụ của một;

BEGIN 
INSERT INTO events (action, E_ID, ID) 
VALUES ('has some news.', NEW.S_ID, NEW.ID); 
END 

Đó là bảng trạng thái của anh ấy.

Có bổ sung cho trình kích hoạt mà tôi có thể thực hiện để đảm bảo NEW.S_ID! = An E_ID hiện tại trong events và nếu thay đổi S_ID tương ứng.

Ngoài ra, có một số loại khóa mà tôi có thể sử dụng để tham chiếu các sự kiện khi tự động tăng S_ID sao cho số S_ID không được tăng lên thành giá trị E_ID.

Đó là những suy nghĩ của tôi, tôi nghĩ giải pháp sau sẽ tốt hơn nhưng tôi nghi ngờ điều đó là có thể hoặc nó sẽ yêu cầu một bảng tham chiếu khác và sẽ quá phức tạp.

+4

Tôi sẽ đề nghị bạn thực sự cần những thứ này để phân bổ id s một trường tăng tự động trên một bảng và sử dụng giá trị từ đó làm id mới khi điền vào một trường trên các bảng khác nhau của bạn. Tuy nhiên tôi muốn có các lĩnh vực id trên bảng khác nhau hoàn toàn độc lập. – Kickstart

Trả lời

12

Rất hiếm khi yêu cầu một id duy nhất trên các bảng, nhưng đây là giải pháp sẽ thực hiện.

/* Create a single table to store unique IDs */ 
CREATE TABLE object_ids (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    object_type ENUM('event', ...) NOT NULL 
) ENGINE=InnoDB; 

/* Independent object tables do not auto-increment, and have a FK to the object_ids table */ 
CREATE TABLE events (
    id INT UNSIGNED NOT NULL PRIMARY KEY, 
    ... 
    CONSTRAINT FOREIGN KEY (id) REFERENCES object_ids (id) 
) ENGINE=InnoDB; 

/* When creating a new record, first insert your object type into the object_ids table */ 
INSERT INTO object_ids(object_type) VALUES ('event'); 
/* Then, get the auto-increment id. */ 
SET @id = LAST_INSERT_ID(); 
/* And finally, create your object record. */ 
INSERT INTO events (id, ...) VALUES (@id, ...); 

Rõ ràng, bạn sẽ lặp lại cấu trúc của bảng events cho các bảng khác.

+0

Tôi biết nó cũ, và trong khi chèn được bảo hiểm, nhưng xóa (và thay đổi) có vẻ khó hơn một chút. Cũng như nó đòi hỏi kỷ luật từ các ứng dụng trong mọi trường hợp. Nó cảm thấy như một giải pháp với kích hoạt có thể là một con đường, ngay ngoài tôi ngay bây giờ. – swa66

+0

Trình kích hoạt có thể hoạt động để xóa, nếu được yêu cầu. Tuy nhiên, tôi không thể nghĩ ra một giải pháp DB trong đó cần xóa vĩnh viễn. Cờ trạng thái "is_active" trên các đối tượng phải phù hợp với 99% các trường hợp. –

3

Bạn cũng có thể chỉ sử dụng Số nhận dạng duy nhất toàn cầu (UUID).

UUID được thiết kế dưới dạng số duy nhất toàn cầu về không gian và thời gian. Hai cuộc gọi đến UUID() dự kiến ​​sẽ tạo ra hai giá trị khác nhau, ngay cả khi các cuộc gọi này được thực hiện trên hai máy tính riêng biệt không được kết nối với nhau.

Vui lòng đọc thêm về nó trong manual.

Ngoài ra còn có shorter version.

+4

Nhược điểm của việc sử dụng UUID là khi bảng của bạn tăng kích thước, việc chèn sẽ trở nên cực kỳ chậm. Vì ID của bạn là khóa chính, nên đó là chỉ mục nhóm của bạn. Mỗi khi bạn chèn UUID, toàn bộ cấu trúc bảng sẽ phải được sử dụng. Điều này có thể mất MINUTES khi bạn nhận được một bảng với hàng triệu bản ghi. Giá trị gia tăng tự động sẽ luôn luôn đi vào cuối, do đó không cần phải sử dụng. –

+0

@StevenMoseley Điều gì về việc sử dụng bigint làm khóa chính của bạn và sử dụng UUID làm cột phụ? Bạn sẽ không thi hành tính toàn vẹn, bạn chỉ nên giả định nó, nhưng tùy thuộc vào nhu cầu của bạn có thể là đủ. Trường hợp xấu nhất bạn có thể kiểm tra UUID trùng lặp theo cách thủ công khi bạn cần mức độ chắc chắn đó nếu dữ liệu đang được chèn từ cuộc gọi API bên ngoài và bạn không chắc chắn về vị trí/cách UUID được tạo. –

+0

@ Le-roy chỉ nhìn thấy câu hỏi này. Nhược điểm là: 1) bạn sẽ tạo ra một chỉ mục nhóm "vứt đi". Trong MySQL, chỉ mục chính (clustered) là BY FAR nhanh nhất cho thời gian tìm kiếm, vì dữ liệu thực sự được sắp xếp theo thứ tự đó, trong khi tất cả các loại chỉ mục khác chứa con trỏ tới dữ liệu ... 2) chính chỉ mục UUID sẽ được sắp xếp trên chèn, mà sẽ làm cho chèn chậm hơn, mặc dù không nhiều như PK UUID), và ... 3) cuối cùng, một UUID có kích thước 9x của một INT. Các chỉ mục MySQL đã chiếm rất nhiều không gian đĩa. Tại sao làm phức tạp chúng bằng cách làm cho chúng lớn hơn 9x so với chúng cần? –

0

UUID_SHORT() nên thực hiện thủ thuật. Nó sẽ tạo ra các số nguyên không dấu 64 bit cho bạn.

Theo doc logic máy phát điện là:

(server_id & 255) << 56 
+ (server_startup_time_in_seconds << 24) 
+ incremented_variable++; 

Giá trị của UUID_SHORT() được đảm bảo là duy nhất nếu các điều kiện sau đây giữ:

  • Giá trị server_id của máy chủ hiện tại nằm trong khoảng từ 0 đến 255 và là duy nhất trong số các máy chủ chủ và máy chủ nô lệ của bạn

  • Y ou không đặt lại thời gian hệ thống cho máy chủ máy chủ của bạn giữa mysqld khởi động lại

  • Bạn có thể gọi UUID_SHORT() trung bình ít hơn 16 triệu lần mỗi giây giữa mysqld khởi động lại

mysql> SELECT UUID_SHORT(); 
    -> 92395783831158784 

Nếu bạn tò mò id máy chủ của bạn là gì, bạn có thể sử dụng một trong hai cách sau:

SELECT @@server_id 
SHOW VARIABLES LIKE 'server_id'; 
Các vấn đề liên quan