2010-05-22 29 views
12

Tôi hoàn toàn bối rối về điều này. Đối với một số lý do khi tôi sắp xếp truy vấn này bởi DESC nó siêu nhanh, nhưng nếu được sắp xếp theo ASC thì nó rất chậm.MySQL ORDER BY DESC là nhanh nhưng ASC là rất chậm

này mất khoảng 150 mili giây:

SELECT posts.id 
FROM posts USE INDEX (published) 
WHERE posts.feed_id IN (4953,622,1,1852,4952,76,623,624,10) 
ORDER BY posts.published DESC 
LIMIT 0, 50; 

này mất khoảng 32 giây:

SELECT posts.id 
FROM posts USE INDEX (published) 
WHERE posts.feed_id IN (4953,622,1,1852,4952,76,623,624,10) 
ORDER BY posts.published ASC 
LIMIT 0, 50; 

Các GIẢI THÍCH là như nhau cho cả hai câu truy vấn.

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE posts index NULL published 5 NULL 50 Using where 

Tôi đã theo dõi nó xuống "SỬ DỤNG INDEX (đã xuất bản)". Nếu tôi lấy nó ra thì đó là cùng một hiệu suất theo cả hai cách. Nhưng giải thích cho thấy truy vấn là tổng thể kém hiệu quả hơn.

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE posts range feed_id feed_id 4 \N 759 Using where; Using filesort 

Và đây là bảng.

CREATE TABLE `posts` (
    `id` int(20) NOT NULL AUTO_INCREMENT, 
    `feed_id` int(11) NOT NULL, 
    `post_url` varchar(255) NOT NULL, 
    `title` varchar(255) NOT NULL, 
    `content` blob, 
    `author` varchar(255) DEFAULT NULL, 
    `published` int(12) DEFAULT NULL, 
    `updated` datetime NOT NULL, 
    `created` datetime NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `post_url` (`post_url`,`feed_id`), 
    KEY `feed_id` (`feed_id`), 
    KEY `published` (`published`) 
) ENGINE=InnoDB AUTO_INCREMENT=196530 DEFAULT CHARSET=latin1; 

Có khắc phục sự cố này không? Cảm ơn!

Trả lời

5

chỉ số của bạn được sắp xếp desc vì vậy khi bạn yêu cầu tăng dần nó cần phải làm rất nhiều công việc hơn để đưa nó trở lại theo thứ tự mà

+0

Cảm ơn bạn đã giải thích. có cách sửa nào cho nó không? Tôi đang suy nghĩ về việc sử dụng 2 truy vấn khác nhau, cái này cho DESC và một cái khác cho ASC. – Pepper

+0

Nếu bạn đang sử dụng mysql 5+, bạn sẽ có thể xác định nhiều chỉ mục. –

+4

Từ http://dev.mysql.com/doc/refman/5.5/vi/create-index.html: Đặc tả index_col_name có thể kết thúc bằng ASC hoặc DESC. Các từ khóa này được phép cho các tiện ích mở rộng trong tương lai để chỉ định bộ nhớ giá trị chỉ mục tăng dần hoặc giảm dần. Hiện tại, chúng được phân tích cú pháp nhưng bị bỏ qua; giá trị chỉ mục luôn được lưu trữ theo thứ tự tăng dần. Vì vậy, làm cách nào tôi có thể tạo chỉ mục được sắp xếp desc? – a1ex07

0

Làm thế nào về flipping điều kiện WHERE?

SELECT posts.id 
FROM posts USE INDEX (published) 
WHERE posts.feed_id IN (10,624,623,76,4952,1852,622,4953) 
ORDER BY posts.published DESC; 
+1

Tôi không hiểu, bạn có thể làm rõ hoặc cung cấp một ví dụ không? – Pepper

+0

SELECT posts.id TỪ bài đăng SỬ DỤNG INDEX (xuất bản) WHERE posts.feed_id IN (10,624,623,76,4952,1852,622,4953) ORDER BY posts.published DESC; cũng ... post.created nên có cùng một phân loại chính xác – user184365

0

Bạn muốn thêm một chỉ số trên (FEED_ID, xuất bản):

ALTER TABLE posts ADD INDEX (feed_id, published) 

Điều đó sẽ làm cho truy vấn này chạy tốt nhất, và bạn sẽ không cần phải buộc một chỉ số đặc biệt với SỬ DỤNG INDEX .

+0

Đây là những gì tôi đã có trước đây, nhưng trên một bảng 500000+ mục nó đã thực hiện chậm. Buộc chỉ mục trên được xuất bản ở trên là khoảng 3x nhanh hơn khi được sắp xếp theo DESC và chậm hơn 10 lần khi được yêu cầu bởi ASC – Pepper

+0

Bạn đã thử chỉ mục chính xác này? Theo thứ tự đó? Xác định "chậm". 500.000 hàng thực sự không phải là vấn đề lớn đối với MySQL (trừ khi máy chủ của bạn là cũ) và với chỉ mục trên hai trường này, truy vấn này sẽ là tất cả chỉ mục bất kể hướng sắp xếp. Điều đó "Sử dụng filesort" trong kế hoạch giải thích của bạn sẽ giúp bạn giải quyết - không có lý do gì sẽ xảy ra khi tối ưu hóa các truy vấn một bảng đơn giản như thế này. Ngoài ra, "được xuất bản" là gì? Có lý do chính đáng nào đó là int (12) không? –

+0

Tôi đoán bởi "chậm" tôi có nghĩa là chậm hơn so với những gì tôi có với phân loại DESC. Nó đang làm một loại: phạm vi, đánh 4000 hàng thay vì 50 và đang sử dụng filesort. – Pepper

1

Tôi sẽ không đề nghị bạn tạo một chỉ mục khác trên bảng; mỗi lần một hàng được chèn hoặc xóa, mỗi chỉ mục trên bảng cần được cập nhật, làm chậm các truy vấn INSERT.

Chỉ số chắc chắn là những gì làm chậm nó xuống. Có lẽ bạn có thể thử IGNORE -ing nó:

SELECT posts.id 
FROM posts IGNORE INDEX (published) 
WHERE posts.feed_id IN (4953,622,1,1852,4952,76,623,624,10) 
ORDER BY posts.published ASC 
LIMIT 0, 50; 

Hoặc, vì lĩnh vực này đã là KEY ed, bạn có thể thử như sau:

SELECT posts.id 
FROM posts USE KEY (published) 
WHERE posts.feed_id IN (4953,622,1,1852,4952,76,623,624,10) 
ORDER BY posts.published ASC 
LIMIT 0, 50; 
+0

Cảm ơn, USE KEY và USE INDEX dường như có cùng kết quả. Và không sử dụng USE INDEX có cùng kết quả như IGNORE INDEX. – Pepper

3

Bạn có thể nhận được dữ liệu của bạn thiết lập đầu tiên, và sau đó theo thứ tự nó.

Something như

SELECT posts.id FROM (
SELECT posts.id 
FROM posts USE INDEX (published) 
WHERE posts.feed_id IN (4953,622,1,1852,4952,76,623,624,10) 
LIMIT 0, 50 
) 
order by postS.id ASC; 

Nó đầu tiên nên sử dụng các chỉ số để tìm tất cả các hồ sơ đáp ứng "ở đâu" tuyên bố của bạn, và sẽ ra lệnh cho họ. Nhưng thứ tự sẽ được thực hiện trong một bộ nhỏ hơn. Hãy thử và sau đó cho chúng tôi biết.

Trân trọng.

+0

Cảm ơn bạn, hãy thử nó. – Pepper

+1

lưu ý nhanh, truy vấn phụ ở trên cần bí danh để hoạt động. – Pepper

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