2011-03-28 40 views
35

Chỉ để nói lên câu hỏi của tôi, tôi hiểu rằng không có hỗ trợ trực tiếp cho một cái gì đó như thế này. Những gì tôi đang tìm kiếm là bất kỳ loại công việc xung quanh, hoặc dẫn xuất phức tạp mà sẽ cho tôi một kết quả một nửa đáng kính.Theo dõi tiến độ truy vấn MySQL dài

Tôi đang làm việc với một cụm MySQL khá lớn (bảng> 400 triệu hàng) bằng cách sử dụng công cụ cụm.

Có ai biết cách để hoặc là truy xuất trực tiếp hoặc nói cách khác là có dấu hiệu tiến bộ chính xác (hoặc tốt hơn) thông qua truy vấn dài trong mysql không? Tôi có một số truy vấn có thể mất tối đa 45 phút và tôi cần xác định xem chúng tôi có 10% hoặc 90% thông qua quá trình xử lý hay không.

EDIT:

Theo yêu cầu trong các ý kiến ​​đây là một phiên bản cất và generified của một của các truy vấn mà đang dẫn đầu cho câu hỏi ban đầu của tôi ...

SELECT `userId` 
FROM `openEndedResponses` AS `oe` 
WHERE 
    `oe`.`questionId` = 3 -- zip code 
    AND (REPLACE(REPLACE(`oe`.`value`, ' ', ''), '-', '') IN ('30071', '30106', '30122', '30134', '30135', '30168', '30180', '30185', '30187', '30317', '30004')); 

Truy vấn này được chạy với một bảng đơn với ~ 95 triệu hàng. Mất 8 giây để chạy truy vấn và 13 giây để chuyển dữ liệu (tổng cộng 21 giây). Xem xét kích thước của bảng, và thực tế là có các chức năng thao tác chuỗi đang được sử dụng, tôi muốn nói nó đang chạy khá nhanh chết tiệt. Tuy nhiên, với người dùng, nó vẫn còn 21 giây xuất hiện hoặc bị mắc kẹt hoặc nhàn rỗi. Một số dấu hiệu của sự tiến bộ sẽ là lý tưởng.

+0

Một truy vấn đơn lẻ mất tối đa 45 phút hoặc có rất nhiều truy vấn INSERT/UPDATE/DELETE nhỏ? –

+0

Chỉ một truy vấn. – KOGI

+0

KOGI, nếu bạn có thể giải quyết vấn đề của mình, bạn nên thêm nó làm câu trả lời. –

Trả lời

1

Hiện tại - đối với trường hợp rất cụ thể của tôi - dường như không có giải pháp thực sự cho việc này. Vì tôi không thể phân tách truy vấn của mình thành một số nhỏ hơn và trước tiên nó phản tác dụng với select count(*) và sau đó chạy truy vấn "thực" (tăng gấp đôi thời gian thực hiện truy vấn chậm), không cách giải quyết nào khả thi.Có thể sớm, MySQL sẽ hỗ trợ một cái gì đó như thế này

+0

Tại sao bạn chọn 'count count (*)'? –

+0

Điều này thực sự là cũ, nhưng 'COUNT (*)' là một cách để xác định có bao nhiêu hàng sẽ có để sắp xếp truy vấn thành nhiều truy vấn nhỏ hơn. – KOGI

7

Tôi đã có thể ước tính điều gì đó như thế này bằng cách truy vấn số hàng để xử lý sau đó phá vỡ quá trình xử lý thành vòng lặp, chỉ làm việc trên một tập con của tổng số hàng tại một thời điểm.

Các vòng lặp đầy đủ khá tham gia, nhưng logic cơ bản đã đi như:

SELECT @minID = Min(keyColumn) FROM table WHERE condition 
SELECT @maxID = Max(keyColumn) FROM table WHERE condition 
SELECT @potentialRows = (@maxID - @minID)/@iterations 

WHILE @minID < @maxID 
BEGIN 
    SET @breakID = @minID + @potentialRows 
    SELECT columns FROM table WITH (NOLOCK, ...) 
    WHERE condition AND keyColumn BETWEEN @minID AND @breakID 

    SET @minID = @breakID + 1 
END 

Lưu ý làm việc này tốt nhất nếu ID được phân bố đều.

+0

Vì vậy, nếu tôi hiểu điều này một cách chính xác, bạn thực hiện truy vấn một lần để nhận được minId, một lần nữa cho maxId, và sau đó là lần thứ 3 (bao gồm nhiều truy vấn con chunked)? Trong khi điều này chắc chắn sẽ cung cấp một số dấu hiệu của sự tiến bộ, nó có hiệu quả gấp ba lần tổng thời gian truy vấn (ở mức tối thiểu, tăng gấp đôi nếu bạn kết hợp xác định min và max thành một truy vấn). Tôi đang thiếu gì? – KOGI

+1

@KOGI: Cung cấp cột mà bạn đang tính toán giá trị MIN/MAX trên được lập chỉ mục, bạn phải kiểm tra thứ gì đó giống như tổng số hàng CEIL (LOG2 (hàng)) - tốn ít thời gian hơn đáng kể. Nếu cột đó không được lập chỉ mục, nó có lẽ nên là nếu SELECT của bạn dựa trên nó, và bạn sẽ phải ăn thời gian chết để thêm chỉ số đó ngay bây giờ bảng của bạn là rất lớn ... –

+0

Cảm ơn, biên dịch Conspicuous. Tôi thích ý tưởng này và cho đến nay nó là lựa chọn tốt nhất mà tôi đã gặp. Tôi tự hỏi tác động hiệu suất sẽ là gì (bỏ qua việc xác định MIN/MAX) để chạy một số truy vấn chunked so với một truy vấn lớn ... – KOGI

2

Tôi không nghĩ rằng mysql hỗ trợ Tôi chắc chắn rằng MySQL không hỗ trợ bất kỳ dấu hiệu nào về tiến trình của các truy vấn đang chạy. Giải pháp duy nhất là tối ưu hóa/tách truy vấn. Chọn có thể được chia theo id như Dour High Arch được đề xuất. Đây là truy vấn từ bảng hàng 33 triệu:

mysql> SELECT SQL_NO_CACHE min(id), max(id) FROM `urls`; 
+---------+----------+ 
| min(id) | max(id) | 
+---------+----------+ 
| 5000 | 35469678 | 
+---------+----------+ 
1 row in set (0.00 sec) 

Bạn nên sử dụng số nguyên ot ít nhất là ngày để tách. Phải là primary hoặc unique chỉ mục và không được cho phép giá trị null.

+1

+1 Không thể chấp nhận bất kỳ câu trả lời nào dưới dạng giải pháp, nhưng ý tưởng và nỗ lực vẫn được đánh giá cao! Cảm ơn! – KOGI

2

Nếu đó là một truy vấn phức tạp mà bạn đang cố gắng, lệnh GIẢI THÍCH SQL hoặc Trình phân tích truy vấn MySQL có thể giúp hiểu những gì đang diễn ra. Nếu nó chỉ đơn giản là một truy vấn lớn, bạn có thể thử tạo một bảng tạm thời với SELECT INTO và/hoặc sử dụng các mệnh đề LIMIT/OFFSET trong các truy vấn SELECT. Nếu bạn sử dụng LIMIT/OFFSET trên các bảng gốc, bạn có thể cần đặt mức giao dịch thành serializable, IIRC, để bạn nhận được các lần đọc nhất quán trong khi lặp qua dữ liệu. Nếu trước tiên bạn tạo một bảng tạm thời, bảng đó phải luôn nhất quán bất kể.

+0

+1 Không thể chấp nhận bất kỳ câu trả lời nào dưới dạng giải pháp, nhưng ý tưởng và nỗ lực vẫn được đánh giá cao! Cảm ơn! – KOGI

0

Làm thế nào về việc tìm kiếm vào phân vùng bảng mysql của bạn để bạn có thể truyền tải đọc/ghi. Nhìn vào cố gắng để hạn chế mỗi phân vùng tới 50 triệu dòng (rõ ràng phụ thuộc vào phần cứng của bạn)

+0

Cảm ơn bạn đã đề xuất. Điều này chắc chắn có tiềm năng để tăng tốc các truy vấn, nhưng bất kể tốc độ, những gì tôi đang tìm kiếm là một cách để theo dõi tiến độ. – KOGI

+0

Ar! Bây giờ tôi đọc lại câu hỏi của bạn Ill có một suy nghĩ. Đó là một phản ứng nhanh chóng trên đường vào công việc :) – Christian

+1

trong suy nghĩ của tôi nếu bạn chia bảng của bạn thành các phân vùng và thậm chí nếu có thể, chia chúng thành các bảng riêng biệt, bạn có thể thực hiện truy vấn của mình nhanh hơn rất nhiều sẽ không phải lo lắng về việc giám sát ... chúng tôi (vì vậy) có thể xem cách tốt nhất để phân vùng, lập chỉ mục, các bảng của bạn để thực hiện nhanh hơn nhiều nếu bạn cung cấp cho chúng tôi các cột và các chức năng đọc/ghi mà bạn cần thực hiện. – Christian

1

Đây là những gì bạn sẽ cần phải làm gì để cải thiện truy vấn sau đây:

SELECT `userId` 
FROM `openEndedResponses` AS `oe` 
WHERE 
    `oe`.`questionId` = 3 -- zip code 
    AND (REPLACE(REPLACE(`oe`.`value`, ' ', ''), '-', '') IN ('30071', '30106', '30122', '30134', '30135', '30168', '30180', '30185', '30187', '30317', '30004')); 

Bạn sẽ cần phải đảm bảo oe .questionId được lập chỉ mục; Bạn sẽ cần đảm bảo oe.value không có bất kỳ khoảng trống nào trên toàn bộ bảng khi oe.questionId là 3; giả sử rằng 4 hoặc 5 có thể là tên thành phố, nơi bạn vẫn muốn cho phép không gian.

Bằng cách này, bạn sẽ có thể xóa tất cả các thay thế, điều này sẽ cho phép MySQL sử dụng chỉ mục trong oe.value.

Sau đó, MySQL sẽ hợp nhất cả hai chỉ mục và cung cấp cho bạn kết quả nhanh hơn nhiều, về mặt xử lý.

Trong trường hợp bạn có nhiều userId lặp lại; bạn sẽ muốn nhóm chúng lại; theo cách mà các mục từ chỉ mục bị loại bỏ ngay lập tức. Bạn vẫn cần quét toàn bộ chỉ mục đã hợp nhất; nhưng kích thước của resultset sẽ mất ít thời gian hơn để được chuyển; ít hơn 13 giây!

Tạo ảnh và giữ cho chúng tôi được đăng về kết quả

Tốt nhất!

+0

Cảm ơn bạn đã đề xuất. Câu hỏi này thực sự cũ, nhưng điều này chắc chắn có tiềm năng để tăng tốc các truy vấn. Tuy nhiên, bất kể tốc độ, những gì tôi đang tìm kiếm là một cách để theo dõi sự tiến bộ. Có một số truy vấn chỉ đơn giản là không nhanh và không thể được tối ưu hóa thêm nữa - tôi cần một cách để xem tiến trình thực hiện truy vấn khi nó chạy. – KOGI

1

Tôi biết đây là một câu hỏi cũ, nhưng tôi đang tìm kiếm một câu trả lời tương tự, khi cố gắng tìm hiểu bản cập nhật của tôi sẽ mất bao nhiêu lâu hơn trên truy vấn 250m hàng.

Nếu bạn chạy:

SHOW ENGINE INNODB STATUS \G 

Sau đó, dưới GIAO DỊCH tìm ra giao dịch trong câu hỏi, kiểm tra phần này:

---TRANSACTION 34282360, ACTIVE 71195 sec starting index read 
mysql tables in use 2, locked 2 
1985355 lock struct(s), heap size 203333840, 255691088 row lock(s), undo log entries 21355084 

Các bit quan trọng là "undo mục log". Đối với mỗi hàng được cập nhật, trong trường hợp của tôi, dường như nó thêm mục nhập nhật ký hoàn tác (thử chạy lại sau vài giây và xem có bao nhiêu lần được thêm).

Nếu bạn bỏ qua để kết thúc báo cáo tình trạng, bạn sẽ thấy điều này:

Number of rows inserted 606188224, updated 251615579, deleted 1667, read 54873415652 
0.00 inserts/s, 1595.44 updates/s, 0.00 deletes/s, 3190.88 reads/s 

Ở đây chúng ta có thể thấy rằng các bản cập nhật tốc độ đang được áp dụng là 1595,44 hàng mỗi giây (mặc dù nếu bạn chạy các truy vấn cập nhật khác song song, tốc độ này có thể được tách biệt giữa các truy vấn của bạn).

Vì vậy, từ đây, tôi biết 21m đã được cập nhật (250m-21m) 229m hàng còn lại để đi.

229.000.000/1600 = 143.125 giây để đi (143.125/60)/60 = 39,76 giờ để đi

Vì vậy, nó sẽ xuất hiện tôi có thể quay vòng ngón tay cái của tôi cho một vài ngày. Trừ khi câu trả lời này là sai, trong trường hợp này tôi sẽ cập nhật nó đôi khi trước đó!

+0

Ahh, nghĩ rằng tôi chỉ làm ồn với điều này, vì một lý do nào đó tôi nghĩ rằng đây là một bản cập nhật, thay vì chọn truy vấn – user7253130

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