2012-07-05 37 views
5

Mysql DB của tôi đã trở thành CPU đói cố gắng thực hiện truy vấn đặc biệt chậm. Khi tôi làm một giải thích, mysql nói "Sử dụng ở đâu; Sử dụng tạm thời; Sử dụng filesort". Hãy giúp giải mã và giải câu đố này.Cần trợ giúp điều chỉnh truy vấn sql

Bảng cấu trúc:

CREATE TABLE `topsources` (
    `USER_ID` varchar(255) NOT NULL, 
    `UPDATED_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `URL_ID` int(11) NOT NULL, 
    `SOURCE_SLUG` varchar(100) NOT NULL, 
    `FEED_PAGE_URL` varchar(255) NOT NULL, 
    `CATEGORY_SLUG` varchar(100) NOT NULL, 
    `REFERRER` varchar(2048) DEFAULT NULL, 
    PRIMARY KEY (`USER_ID`,`URL_ID`), 
    KEY `USER_ID` (`USER_ID`), 
    KEY `FEED_PAGE_URL` (`FEED_PAGE_URL`), 
    KEY `SOURCE_SLUG` (`SOURCE_SLUG`), 
    KEY `CATEGORY_SLUG` (`CATEGORY_SLUG`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 

Bảng này có 370K hàng ... đôi khi cao hơn. Truy vấn dưới đây mất hơn 10 giây.

SELECT topsources.SOURCE_SLUG, COUNT(topsources.SOURCE_SLUG) AS VIEW_COUNT 
FROM topsources 
WHERE CATEGORY_SLUG = '/newssource' 
GROUP BY topsources.SOURCE_SLUG 
HAVING MAX(CASE WHEN topsources.USER_ID = 'xxxx' THEN 1 ELSE 0 END) = 0 
ORDER BY VIEW_COUNT DESC; 

Dưới đây là các mở rộng giải thích:

+----+-------------+------------+------+---------------+---------------+---------+-------+--------+----------+----------------------------------------------+ 
| id | select_type | table  | type | possible_keys | key   | key_len | ref | rows | filtered | Extra          | 
+----+-------------+------------+------+---------------+---------------+---------+-------+--------+----------+----------------------------------------------+ 
| 1 | SIMPLE  | topsources | ref | CATEGORY_SLUG | CATEGORY_SLUG | 302  | const | 160790 | 100.00 | Using where; Using temporary; Using filesort | 
+----+-------------+------------+------+---------------+---- 

----------- + --------- + ------- + - ------- + ---------- + ------------------------------- --------------- +

Có cách nào để cải thiện truy vấn này không? Ngoài ra, có bất kỳ cài đặt mysql nào có thể giúp giảm tải CPU không? Tôi có thể phân bổ thêm bộ nhớ có sẵn trên máy chủ của tôi.

+1

CÓ MAX (CASE KHI topsources.USER_ID = 'xxxx' THÌ 1 ELSE 0 END) = 0 phần này là vấn đề nhất tôi nghĩ hãy để tôi nghĩ làm thế nào để làm điều này tốt hơn – Jester

+0

nó muốn giúp đỡ để đăng đầu ra chính xác từ giải thích –

+0

Cập nhật diễn ra trong khi bạn đang chạy truy vấn? –

Trả lời

0

Điều đó sẽ làm các trick nếu tôi đọc sql thay đổi này correcty tôi

SELECT topsources.SOURCE_SLUG, COUNT(topsources.SOURCE_SLUG) AS VIEW_COUNT 
FROM topsources 
WHERE CATEGORY_SLUG = '/newssource' and 
    topsources.SOURCE_SLUG not in (
     select distinct SOURCE_SLUG 
     from topsources 
     where USER_ID = 'xxxx' 
     ) 
GROUP BY topsources.SOURCE_SLUG 
ORDER BY VIEW_COUNT DESC; 
+0

Truy vấn này trả về một tập kết quả khác. Không giống như truy vấn ban đầu. – Zero

+0

Đã cập nhật truy vấn thử yêu cầu đó – Jester

1

Điều có khả năng nhất để giúp truy vấn là một chỉ mục trên CATEGORY_SLUG, đặc biệt là nếu phải mất nhiều giá trị. (Nghĩa là, nếu truy vấn có tính chọn lọc cao.) Truy vấn cần đọc toàn bộ bảng để nhận được kết quả - mặc dù 10 giây có vẻ như là một thời gian dài.

Tôi không nghĩ rằng mệnh đề HAVING sẽ ảnh hưởng đến xử lý truy vấn.

Truy vấn chỉ mất nhiều thời gian nếu bạn chạy truy vấn hai lần liên tiếp?

+0

Đã có chỉ mục trên CATEGORY_SLUG. Vui lòng đọc cấu trúc bảng ở trên. Truy vấn hầu như luôn mất nhiều thời gian hơn để chạy. – Zero

+0

Hmmm, có bao nhiêu loại sên? Đôi khi, các chỉ mục làm hại nhiều hơn lợi ích, đặc biệt khi chỉ có một số ít giá trị. –

+0

Ít hơn 100 loại sên. – Zero

0

Nếu có nhiều hàng phù hợp với tiêu chí CATEGORY_SLUG của bạn, có thể khó thực hiện điều này nhanh chóng, nhưng điều này có nhanh hơn không?

SELECT ts.SOURCE_SLUG, COUNT(ts.SOURCE_SLUG) AS VIEW_COUNT 
FROM topsources ts 
WHERE ts.CATEGORY_SLUG = '/newssource' 
    AND NOT EXISTS(SELECT 1 FROM topsources ts2 
       WHERE ts2.CATEGORY_SLUG = '/newssource' 
        AND ts.SOURCE_SLUG = TS2.SOURCE_SLUG 
        AND ts2.USER_ID = 'xxxx') 
GROUP BY ts.SOURCE_SLUG 
ORDER BY VIEW_COUNT DESC; 
+0

Trả về truy vấn Cột không xác định 'TS2.SOURCE_SLUG' trong 'khoản' – Zero

+0

xóa dòng của mình 'AND ts.SOURCE_SLUG = TS2.SOURCE_SLUG' – jared

+0

Nếu tôi xóa dòng đó, thì truy vấn này trả về tập kết quả trống – Zero

0

Luôn cứng để tối ưu hóa một cái gì đó khi bạn không thể chỉ ném thắc mắc tại dữ liệu cho mình, nhưng điều này sẽ là nỗ lực đầu tiên của tôi nếu tôi đã làm nó bản thân mình:

SELECT t.SOURCE_SLUG, COUNT(t.SOURCE_SLUG) AS VIEW_COUNT 
FROM topsources t 
LEFT JOIN (
    SELECT SOURCE_SLUG 
    FROM topsources t 
    WHERE CATEGORY_SLUG = '/newssource' 
    AND USER_ID = 'xxx' 
    GROUP BY .SOURCE_SLUG 
) x USING (SOURCE_SLUG) 
WHERE t.CATEGORY_SLUG = '/newssource' 
AND x.SOURCE_SLUG IS NULL 
GROUP BY t.SOURCE_SLUG 
ORDER BY VIEW_COUNT DESC; 
Các vấn đề liên quan