2015-10-23 9 views
5

Dưới đây là ba Truy vấn MySQL. Việc đầu tiên trả về tất cả mọi thứ tôi đang tìm kiếm trong một truy vấn, trong khi hai thứ hai trả về cùng một kết quả tổng hợp, nhưng trong hai truy vấn.Tại sao các Truy vấn MySQL này lại mất một lượng thời gian đáng kể khác nhau để xử lý khi chúng có vẻ tương đương?

Tôi tự hỏi tại sao một truy vấn đơn tốn từ 2-100 lần để chạy, khi có vẻ như thời gian xử lý phải tương đương giữa cả ba truy vấn. Có cách nào để tối ưu hóa truy vấn đơn lẻ để chạy nhanh như các truy vấn riêng lẻ không? Thêm nhiều OR bên trong câu lệnh WHERE của truy vấn đơn không làm tăng thời gian xử lý, nhưng tôi có các trường hợp cần phải thực hiện nhiều OR và cuối cùng truy vấn đơn sẽ nhanh bằng cách chạy mười truy vấn riêng lẻ.

Truy vấn đơn lẻ cũng dường như được lưu trong bộ nhớ cache sau khi nó chạy và có thể mất vài phút để chạy lần đầu tiên, trong khi các truy vấn đơn luôn hoàn tất trong cùng một khung thời gian.

Chỉ mục nhiều cột có tạo nên sự khác biệt lớn ở đây không?

Lưu ý là bảng không có trường ID làm chỉ mục chính. Điều này có gây ra hành vi không mong muốn này không?

Thật khó để chạy thử nghiệm ở đây vì bảng có hàng trăm triệu hàng và thêm cột và chỉ mục mất gần một ngày.

SINGLE QUERY (4.2s)

SELECT name_id 
FROM staging_company_search 
WHERE 
    (name_word_0 = 'the' AND name_word_1 = 'glazier') 
    OR (name_word_0 = 'bridgewaters' AND name_word_1 = ''); 

GỘP TƯƠNG ĐƯƠNG truy vấn (0.8s mỗi)

SELECT name_id 
FROM staging_company_search 
WHERE name_word_0 = 'the' AND name_word_1 = 'glazier'; 

SELECT name_id 
FROM staging_company_search 
WHERE name_word_0 = 'bridgewaters' AND name_word_1 = ''; 

GIẢI THÍCH VỀ NHỮNG VƯỚNG MẮC

id  select_type table      type possible_keys    key   key_len ref rows  extra 
1  SIMPLE   staging_company_search range name_word_0,name_word_1 name_word_0 102  NULL 2197605 Using index condition; Using where 
1  SIMPLE   staging_company_search ref  name_word_0,name_word_1 name_word_1 102  const 128  Using index condition; Using where 
1  SIMPLE   staging_company_search ref  name_word_0,name_word_1 name_word_0 102  const 33  Using index condition; Using where 

DATABASE SCHEMA

CREATE TABLE `staging_company_search` (
    `name_id` int(11) unsigned NOT NULL DEFAULT '0', 
    `name_word_0` varchar(100) NOT NULL, 
    `name_word_1` varchar(100) NOT NULL, 
    KEY `name_id` (`name_id`), 
    KEY `name_word_0` (`name_word_0`), 
    KEY `name_word_1` (`name_word_1`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 
+0

gì xảy ra nếu bạn cố gắng ĐÂU (name_word_0, name_word_1) trong (('the', 'nghề làm kiếng'), ('bridgewaters', '')) trong truy vấn đầu tiên? –

+0

Thậm chí chậm hơn. Truy vấn đó cũng chứa logic hơi khác và kết quả trong bốn kết hợp của name_words trái ngược với hai. –

+0

Tôi hiểu. Làm thế nào về một liên minh của hai truy vấn tổng hợp tương đương? EXPLAIN PLAN có cho thấy sự khác biệt nào giữa hai điều này không? –

Trả lời

2

Điều này là do mysql chỉ sử dụng một chỉ mục cho truy vấn đơn giản.

Nếu có một sự lựa chọn giữa nhiều chỉ số, MySQL thường sử dụng chỉ số đó tìm số nhỏ nhất của dãy (các chọn lọc nhất index).

Tuy nhiên mysql có thể và sẽ sử dụng hai chỉ mục từ phiên bản 5.0 đến Index merge optimization. Thật không may nó không phải luôn luôn xảy ra và ngay cả khi nó xảy ra kết quả aren't all that great.

Đầu ra giải nghĩa đầu tiên cho thấy tối ưu hóa hợp nhất chỉ mục không được sử dụng trong truy vấn của bạn với mệnh đề OR. Nó chỉ sử dụng các chỉ mục trên name_word_0

name_word_0 là rất tốt cho WHERE name_word_0 = 'the' AND name_word_1 = 'glazier'; nhưng như đầu ra cho ba giải thích cho thấy, nó không phải là ở tất cả thích hợp cho WHERE name_word_0 = 'bridgewaters' AND name_word_1 = '';

Do đó truy vấn kết hợp là rất chậm. YOu có thể khắc phục điều đó bằng cách tạo chỉ mục tổng hợp kéo dài name_word_0 và name_word_1. Tôi nhận thấy rằng len chính của bạn thực sự là dài. YOu có thể tạo chỉ mục một phần và có thể tăng tốc độ hơn nữa.

CREATE INDEX word01 ON staging_company_search (name_word_0(20), name_word_1(20)) 
2

Tôi không phải là một chuyên gia, nhưng tôi tin rằng điều này là do cách MySQL xử lý các chỉ số mà nó phải kiểm tra một số điều kiện ("OR"). Điều này được nhìn thấy trong "truy vấn giải nghĩa", nơi truy vấn đầu tiên được mong đợi cần phải kiểm tra nhiều hàng hơn trước khi trả về kết quả.

Tôi tin rằng sự kết hợp của hai kết quả nhỏ sẽ đạt được hiệu suất tốt hơn. Bạn có thể thử những điều sau đây không?

SELECT name_id 
FROM staging_company_search 
WHERE (name_word_0 = 'the' AND name_word_1 = 'glazier') 
UNION ALL  
    SELECT name_id 
    FROM staging_company_search 
    WHERE (name_word_0 = 'bridgewaters' AND name_word_1 = ''); 
2

Việc bạn sử dụng mệnh đề OR trong truy vấn đầu tiên sẽ đánh bại việc sử dụng chỉ mục của bạn. MySQL là một chút ngu ngốc theo cách đó. Nó đang thực hiện quét toàn bộ bảng: nhìn vào mọi hàng. Bạn nên sử dụng các truy vấn AND-only UNIONed cùng nhau tốt hơn nhiều.

Để làm cho truy vấn AND của bạn thậm chí nhanh hơn, hãy tạo chỉ mục phức hợp trên (name_word_0, name_word_1, name_id). Truy vấn của bạn có thể hoàn toàn hài lòng bởi một truy cập ngẫu nhiên vào chỉ mục đó và sẽ chạy dưới giây với một bảng hai megarow.

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