2013-09-06 62 views
18

Tôi đang đối mặt với một vấn đề hiệu suất lạ với truy vấn mysql.mysql: tại sao không tham gia không sử dụng chỉ mục?

SELECT 
`pricemaster_products`.*, 
`products`.* 
FROM `pricemaster_products` 
LEFT JOIN `products` 
ON `pricemaster_products`.`ean` = `products`.`products_ean` 

Tôi rõ ràng muốn sử dụng phép nối trái. Nhưng truy vấn mất rất nhiều thời gian hơn sau đó nó nên.

Tôi đã cố gắng thay đổi kết nối với INNER JOIN. Truy vấn bây giờ thực sự nhanh, nhưng kết quả không phải là những gì tôi cần.

Tôi đã từng giải thích và đi đến kết luận sau:

Nếu tôi sử dụng một "LEFT JOIN", sau đó một giải thích các kết quả truy vấn trong ...

type: "ALL" 
possible_keys: NULL 
key: NULL 
key_len: NULL 
ref: NULL 
rows: 90.000/50.000 (the full number of the corresponding table) 

... cho cả hai bảng .

Nếu tôi sử dụng một "INNER JOIN", sau đó giải thích cho:

Đối với "sản phẩm" bảng:

Same result as above. 

Đối với bảng "pricemaster_products":

type: "ref" 
possible_keys: "ean" 
key: ean 
key_len: 767 
ref: func 
rows: 1 
extra: using where 

Cả hai bảng có chỉ số đặt trên các cột có liên quan. Lý do duy nhất tôi có thể nghĩ đến cho LEFT JOIN là quá chậm là không sử dụng chỉ mục chút nào. Nhưng tại sao nó không?

Cấu trúc bảng như sau:

CREATE TABLE IF NOT EXISTS `pricemaster_products` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `provider` varchar(255) CHARACTER SET utf8 NOT NULL, 
    `ean` varchar(255) CHARACTER SET utf8 NOT NULL, 
    `title` varchar(255) CHARACTER SET utf8 NOT NULL, 
    `gnp` double DEFAULT NULL, 
    `vat` int(11) DEFAULT NULL, 
    `cheapest_price_with_shipping` double DEFAULT NULL, 
    `last_cheapest_price_update` int(11) DEFAULT NULL, 
    `active` tinyint(1) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id`), 
    KEY `ean` (`ean`), 
    KEY `title` (`title`), 
    KEY `gnp` (`gnp`), 
    KEY `vat` (`vat`), 
    KEY `provider` (`provider`), 
    KEY `cheapest_price_with_shipping` (`cheapest_price_with_shipping`), 
    KEY `last_cheapest_price_update` (`last_cheapest_price_update`), 
    KEY `active` (`active`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=58436 ; 

CREATE TABLE IF NOT EXISTS `products` (
    `products_id` int(11) NOT NULL AUTO_INCREMENT, 
    `products_ean` varchar(128) DEFAULT NULL, 
    `products_status` tinyint(1) NOT NULL DEFAULT '1', 
    [a lot more of fields with no connection to the query in question] 
    PRIMARY KEY (`products_id`), 
    KEY `products_status` (`products_status`), 
    KEY `products_ean` (`products_ean`), 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=105518 ; 
+0

Bạn đang sử dụng phiên bản MySQL nào? –

+0

Phiên bản MySQL là 5.1.70 – Majiy

+1

@juergend: không, đó là "cung cấp cho tôi tất cả dữ liệu trong bảng bên trái và mọi dữ liệu có sẵn trong bảng bên phải". bạn đang suy nghĩ một tham gia bên ngoài đầy đủ –

Trả lời

39

Hai lĩnh vực có liên quan cho tham gia không có chính xác cùng loại (varchar (255) với CHARACTER SET utf8 và varchar (128) với latin1). Tôi đã thiết lập cả hai chiều dài và ký tự cùng một bộ, và bây giờ truy vấn với LEFT JOIN hoạt động như mong đợi.

+3

Holy f *** ing sh * t. Tôi đã nhìn toàn bộ điều này. Cảm ơn. +1 –

+2

Cảm ơn bạn rất nhiều điều này đã giúp tôi tìm thấy một vấn đề với một trong các truy vấn của tôi, nơi một bảng được tạo không chính xác (sử dụng bộ ký tự sai) đang tạo ra sự cố. +1 –

+1

cảm ơn bạn rất nhiều tôi đã có cùng một vấn đề này và nó đã lái xe cho tôi hoàn toàn chuối – caro