2012-03-06 51 views
7

Tôi có cơ sở dữ liệu với hơn 75.000 hàng với hơn 500 mục được thêm mỗi ngày.Cách hiệu quả nhất để tìm kiếm trong SQL?

Mỗi hàng có tiêu đề và mô tả.

Tôi đã tạo nguồn cấp dữ liệu RSS cung cấp cho bạn các mục nhập mới nhất cho cụm từ tìm kiếm cụ thể (ví dụ: http://site.com/rss.rss?q=Pizza sẽ xuất ra RSS cho cụm từ tìm kiếm "Pizza").

Tôi đã tự hỏi điều gì sẽ là cách tốt nhất để viết truy vấn SQL cho điều này. Ngay bây giờ tôi có:

SELECT * 
FROM 'table' 
WHERE (('title' LIKE %searcherm%) OR ('description' LIKE %searcherm%)) 
LIMIT 20; 

Nhưng vấn đề là phải mất từ ​​2 đến 10 giây để thực hiện truy vấn.

Có cách nào tốt hơn để viết các truy vấn, làm tôi phải cache kết quả (và làm thế nào tôi sẽ làm điều đó?) Hoặc sẽ thay đổi điều gì đó trong tốc độ cấu trúc cơ sở dữ liệu lên các truy vấn (chỉ số?)

+0

có thể nhanh hơn vào chủ đề cá nhân/ngã ba chế biến thành 2 querys đơn giản: 'lựa chọn tuyệt vời trong đó giới hạn tiêu đề 20' thì 'chọn từ bảng có giới hạn mô tả 20' điều gì đó, sau đó thực hiện kết hợp/danh sách với công nghệ phía máy chủ của bạn –

+0

solr, lucene, sphinx? –

Trả lời

8

Một giải pháp tương đối đơn giản cho điều này sẽ được kết hợp một chỉ mục toàn văn trên hai và sau đó tìm kiếm bằng cách sử dụng chỉ mục này.

ALTER TABLE table ADD FULLTEXT(title, description); 

Sau đó, bạn sẽ cần phải thực hiện tìm kiếm, bạn sẽ làm như sau:

SELECT id FROM table 
WHERE MATCH (title, description) AGAINST ('keyterm'); 

Fulltext lập chỉ mục tìm kiếm sự là giải pháp tự động bao gồm trong hầu hết các cơ sở dữ liệu SQL. Đó là nhanh hơn nhiều so với làm LIKES. Điều này cũng được tối ưu hóa cho trường hợp cụ thể của bạn bởi vì bạn chỉ quan tâm đến các thuật ngữ tìm kiếm ngôn ngữ tự nhiên.

Đồng thời, chỉ mục toàn văn có một số thuật toán hạn chế để phát hiện mức độ liên quan. Bạn có thể đọc thêm về nó here

EDIT

Trong tuyên bố alter, tôi đã bỏ lỡ tên chỉ số toàn văn, nó phải là:

ALTER TABLE table ADD FULLTEXT ft_index_name(title, description); 
+0

Tôi sẽ thử điều đó. Cảm ơn! – supercoolville

+0

Lưu ý rằng điều này sẽ chỉ hoạt động với các bảng MyISAM, không phải InnoDB. –

+1

Cảm ơn rất nhiều !!! Tôi đã thử nghiệm điều này và nó làm cho tìm kiếm của tôi nhanh hơn trung bình 14 lần !!!!!!! – supercoolville

-2

Một vài gợi ý: Thả dấu * vào câu lệnh chọn của bạn và chỉ kéo các tiêu chí tìm kiếm, và đảm bảo thêm các chỉ mục vào các cột đang được tìm kiếm.

SELECT `title`,`description` 
FROM `table` 
WHERE `title` LIKE '%$searchterm%' OR `description` LIKE '%$searchterm%' LIMIT 25; 
+0

"Thả * trong câu lệnh chọn của bạn và chỉ kéo tiêu chí tìm kiếm" - cũng làm cách nào bạn biết những gì anh ta muốn truy xuất? –

+0

Tôi không, nhưng dựa trên mệnh đề WHERE của mình, tôi có thể xác định anh ấy cần ở tiêu đề LEAST và mô tả. Bất kể, nó luôn luôn tốt hơn để xác định các bảng của bạn chứ không phải là ký tự đại diện, ông được hỏi làm thế nào để tăng tốc độ truy vấn và loại bỏ ký tự đại diện là bước đầu tiên. –

+0

có giới hạn 20 .. Tôi nghi ngờ rằng nó sẽ tạo ra bất kỳ sự khác biệt có thể đo lường được –

-2
  1. Bạn có tạo ra một chỉ số cho title và cho description?
  2. Bạn nên xem xét Sphinx cho khả năng Tìm kiếm toàn văn bản.

Cảm ơn Tyler nhận xét.

tôi trình bày lại câu trả lời của tôi:

1) Tạo một chỉ mục trên titledescription cột, nhưng truy vấn của bạn sẽ được giới hạn ở những ví dụ dưới đây, và đó không phải là lý tưởng cho việc tìm kiếm tất cả các hàng có liên quan:

SELECT * 
FROM 'table' 
WHERE title LIKE 'searcherm%' OR description LIKE 'searcherm%' 
LIMIT 20; 

2) Như những người khác đã đề cập, sử dụng MySQL Full-Text Search, nhưng bạn bị giới hạn đối với công cụ bảng MyISAM, vì nó không có sẵn cho InnoDB. Tuy nhiên, bạn có thể trộn các công cụ trong MySQL, vì vậy bạn có thể làm cho bảng MyISAM này, ngay cả khi tất cả các bảng khác của bạn là InnoDB.

3) Sử dụng công cụ Tìm kiếm toàn văn bản bên ngoài, chẳng hạn như Sphinx. Điều này sẽ cung cấp cho bạn kết quả tìm kiếm có liên quan hơn (Tìm kiếm toàn văn bản MySQL để lại nhiều điều mong muốn), nó sẽ hoạt động tốt hơn và tóm tắt gánh nặng tìm kiếm toàn văn bản khỏi cơ sở dữ liệu của bạn.

+2

Chỉ số sẽ không trợ giúp ở đây. Giống như '% foo%' không bao giờ sử dụng chỉ mục. Đó là vấn đề thực sự của anh ấy. –

4

Hãy thử:

SELECT * FROM table 
WHERE MATCH (title,description) AGAINST (searchterm); 

Hãy chắc chắn rằng bạn thêm một chỉ mục văn bản đầy đủ về tiêu đề, mô tả lại với nhau.

Không cố gắng phát minh lại bánh xe. MATCHAGAINSTprovided by mysql để thực hiện chính xác điều đó và làm cho cuộc sống của bạn trở nên dễ dàng. Tuy nhiên, lưu ý tìm kiếm văn bản đầy đủ hoạt động trên các bảng MyISAM. Bạn can workaround cho InnoDb quá.Bạn chỉ có thể thêm FT chỉ số bằng cách thay đổi bảng như:

ALTER TABLE table ADD FULLTEXT(title,description); 
+0

Đây là câu trả lời duy nhất có thể hoạt động. Đề cập rằng bạn cần thêm chỉ mục toàn văn vào các cột này và bạn phải sử dụng bảng MyISAM. –

+0

@FrancisAvila Đã cập nhật câu trả lời của tôi. – jerrymouse

2

Nếu bạn đang sử dụng một truy vấn với LIKE '%term%' các chỉ số không thể được sử dụng. Chúng chỉ có thể được sử dụng nếu bạn sử dụng truy vấn như 'term%'. Hãy suy nghĩ về sổ địa chỉ có tab, bạn có thể tìm các liên hệ thực sự nhanh bắt đầu bằng chữ cái L, nhưng để tìm địa chỉ liên hệ với một số on ở đâu đó trong từ, bạn phải quét toàn bộ sổ địa chỉ.

Các lựa chọn tốt hơn có thể được sử dụng chỉ mục văn bản đầy đủ:

CREATE FULLTEXT INDEX title_desc 
ON table (title, description) 

Và sau đó trong truy vấn:

SELECT title, description FROM table 
WHERE MATCH (title, description) AGAINST ('+Pizza') 
0

tôi sẽ đi với câu trả lời gtr32x của JohnB hay (Lập chỉ mục toàn văn). Để bổ sung cho câu trả lời của họ, có một cách thủ công để tạo một chỉ mục văn bản đầy đủ đơn giản và cực kỳ nhanh chóng ...

Chia tiêu đề và mô tả thành từ khóa và đặt chúng vào một bảng Keywords. bài viết RSS gốc. Đảm bảo cột từ khóa trong Keywords được lập chỉ mục. Bạn có thể làm điều gì đó như:

SELECT DISTINCT ra.* 
FROM RssArticle ra 
INNER JOIN Keywords k ON k.ArticleID = ra.ArticleID 
    WHERE k IN ('SearchTerm1', 'SearchTerm2', 'SearchTerm3') 
LIMIT 20; 

Và thật nhanh!

+0

Tôi không chắc chắn ý bạn là gì ... – supercoolville

0

Hãy thử một trong bốn câu hỏi sau đây:

select * from myTable where concat_ws(' ',title,description) like '%pizza%'; 
select * from myTable where concat_ws(' ',title,description) regexp '.*pizza+.*'; 
select title,description from myTable where concat_ws(' ',title,description) like '%pizza%'; 
select title,description from myTable where concat_ws(' ',title,description) regexp '.*pizza+.*'; 

điểm là sử dụng concat trước khi tìm kiếm

+0

tốc độ này nhanh hơn gấp 2 lần nhưng không nhanh bằng MATCH AGAINST – supercoolville

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