Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

làm thế nào để triển khai tìm kiếm cho 2 dữ liệu bảng khác nhau?

Dưới đây là một vài "luật chơi" mà bạn phải ghi nhớ để giải quyết vấn đề này. Có thể bạn đã biết những điều này, nhưng việc trình bày rõ ràng có thể giúp xác nhận cho những người đọc khác.

  • Tất cả các chỉ mục trong MySQL chỉ có thể tham chiếu đến các cột trong một bảng cơ sở duy nhất. Bạn không thể tạo chỉ mục toàn văn để lập chỉ mục trên nhiều bảng.
  • Bạn không thể xác định chỉ mục cho các chế độ xem, chỉ các bảng cơ sở.
  • MATCH() truy vấn đối với chỉ mục toàn văn bản phải khớp với tất cả các cột trong chỉ mục văn bản đầy đủ, theo thứ tự được khai báo trong chỉ mục.

Tôi sẽ tạo một bảng thứ ba để lưu trữ nội dung bạn muốn lập chỉ mục. Không cần lưu trữ nội dung này dư thừa - chỉ lưu trữ nội dung này trong bảng thứ ba. Điều này vay mượn khái niệm về "lớp cha chung" từ thiết kế hướng đối tượng (trong chừng mực chúng ta có thể áp dụng nó cho thiết kế RDBMS).

CREATE TABLE Searchable (
  `id` SERIAL PRIMARY KEY,
  `title` varchar(100) default NULL,
  `description` text,
  `keywords` text,
  `url` varchar(255) default '',
  FULLTEXT KEY `TitleDescFullText` (`keywords`,`title`,`description`,`url`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE `shopitems` (
  `id` INT UNSIGNED NOT NULL,
  `ShopID` INT UNSIGNED NOT NULL,
  `ImageID` INT UNSIGNED NOT NULL,
  `pricing` varchar(45) NOT NULL,
  `datetime_created` datetime NOT NULL,
  PRIMARY KEY (`id`),
  FOREIGN KEY (`id`) REFERENCES Searchable (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE `shops` (
  `id` INT UNSIGNED NOT NULL,
  `owner_id` varchar(255) default NULL,
  `datetime_created` datetime default NULL,
  `created_by` varchar(255) default NULL,
  `datetime_modified` datetime default NULL,
  `modified_by` varchar(255) default NULL,
  `overall_rating_avg` decimal(4,2) default '0.00',
  PRIMARY KEY (`id`),
  FOREIGN KEY (`id`) REFERENCES Searchable (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Lưu ý rằng bảng duy nhất có khóa tăng tự động hiện là bảng Searchable . Các bảng shopsshopitems sử dụng khóa có kiểu dữ liệu tương thích, nhưng không tự động tăng. Vì vậy, bạn phải tạo một hàng trong Searchable để tạo id giá trị, trước khi bạn có thể tạo hàng tương ứng trong shops hoặc shopitems .

Tôi đã thêm FOREIGN KEY khai báo cho mục đích minh họa, mặc dù MyISAM sẽ im lặng bỏ qua những ràng buộc này (và bạn đã biết rằng bạn phải sử dụng MyISAM để hỗ trợ lập chỉ mục toàn văn bản).

Bây giờ bạn có thể tìm kiếm nội dung văn bản của cả shopsshopitems trong một truy vấn, sử dụng một chỉ mục toàn văn:

SELECT S.*, sh.*, si.*,
  MATCH(keywords, title, description, url) AGAINST('dummy') As score
FROM Searchable S
LEFT OUTER JOIN shops sh ON (S.id = sh.id)
LEFT OUTER JOIN shopitems si ON (S.id = si.id)
WHERE MATCH(keywords, title, description, url) AGAINST('dummy')
ORDER BY score DESC;

Tất nhiên, đối với một hàng nhất định trong Searchable chỉ nên khớp một bảng, cửa hàng hoặc shopitem và các bảng này có các cột khác nhau. Vì vậy, một trong hai sh.* hoặc si.* sẽ là NULL trong kết quả. Định dạng đầu ra trong ứng dụng của bạn là tùy thuộc vào bạn.

Một số câu trả lời khác đã đề xuất sử dụng Sphinx Search . Đây là một công nghệ khác bổ sung cho MySQL và thêm khả năng tìm kiếm toàn văn bản phức tạp hơn. Nó có hiệu suất tuyệt vời cho các truy vấn, vì vậy một số người đã khá thích thú với nó.

Nhưng việc tạo chỉ mục và đặc biệt là thêm vào một chỉ mục tăng dần thì rất tốn kém. Trên thực tế, việc cập nhật chỉ mục Sphinx Search rất tốn kém nên giải pháp được đề xuất là tạo một chỉ mục cho dữ liệu cũ hơn, được lưu trữ và một chỉ mục khác nhỏ hơn cho dữ liệu gần đây có nhiều khả năng được cập nhật hơn. Sau đó, mọi tìm kiếm phải chạy hai truy vấn, đối với hai chỉ mục riêng biệt. Và nếu dữ liệu của bạn không tự nhiên phù hợp với kiểu dữ liệu cũ hơn là không thay đổi, thì bạn có thể không tận dụng được thủ thuật này.

Nhận xét của bạn:Đây là đoạn trích từ tài liệu về Sphinx Search về các bản cập nhật trực tiếp cho một chỉ mục:

Ý tưởng là vì việc cập nhật chỉ mục Sphinx Search rất tốn kém, nên giải pháp của họ là làm cho chỉ mục bạn cập nhật càng nhỏ càng tốt. Vì vậy, chỉ các bài đăng trên diễn đàn gần đây nhất (trong ví dụ của họ), trong khi lịch sử lớn hơn của các bài đăng trên diễn đàn được lưu trữ không bao giờ thay đổi, vì vậy bạn tạo chỉ mục thứ hai, lớn hơn cho bộ sưu tập đó một lần. Tất nhiên, nếu bạn muốn thực hiện tìm kiếm, bạn phải truy vấn cả hai chỉ mục.

Định kỳ, giả sử mỗi tuần một lần, các thông báo trên diễn đàn "gần đây" sẽ được coi là "đã lưu trữ" và bạn phải hợp nhất chỉ mục hiện tại cho các bài đăng gần đây với chỉ mục đã lưu trữ và bắt đầu lại chỉ mục nhỏ hơn. Họ đưa ra quan điểm rằng việc hợp nhất hai chỉ mục Sphinx Search sẽ hiệu quả hơn việc lập chỉ mục lại sau khi cập nhật dữ liệu.

Nhưng quan điểm của tôi là không phải mọi tập dữ liệu đều rơi vào mô hình có một tập dữ liệu được lưu trữ mà không bao giờ thay đổi, so với dữ liệu gần đây cập nhật thường xuyên.

Lấy cơ sở dữ liệu của bạn làm ví dụ:Bạn có cửa hàng và shopitem. Làm cách nào bạn có thể tách những hàng này thành các hàng không bao giờ thay đổi so với các hàng mới? Bất kỳ cửa hàng hoặc sản phẩm nào trong danh mục đều được phép cập nhật mô tả của chúng. Nhưng vì điều đó đòi hỏi phải xây dựng lại toàn bộ chỉ mục Sphinx Search mỗi khi bạn thực hiện thay đổi, nên nó sẽ trở thành một hoạt động rất tốn kém. Có lẽ bạn sẽ xếp hàng các thay đổi và áp dụng hàng loạt, xây dựng lại chỉ mục mỗi tuần một lần. Nhưng hãy thử giải thích cho các nhà cung cấp cửa hàng tại sao một thay đổi nhỏ đối với mô tả cửa hàng của họ sẽ không có hiệu lực cho đến tối Chủ nhật.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Rails ActiveRecord - có cách nào để thực hiện các thao tác trên bảng mà không cần id không?

  2. mySQL select IN range

  3. Thiết kế cơ sở dữ liệu quy tắc giá cho hệ thống đặt phòng khách sạn

  4. SQL Tham gia cùng một bảng dựa trên tem thời gian và mức tồn kho

  5. PHP Tập lệnh đăng nhập lần cuối