2009-05-14 32 views
24

Một trong các truy vấn của tôi trên MySQL 5.0.45 đang chạy chậm trong giai đoạn "gửi dữ liệu". Truy vấn là một lựa chọn đơn giản, trả về khoảng 300 trường ID nguyên như tập kết quả.MySql - chậm gửi dữ liệu giai đoạn

 
mysql> SELECT source_id FROM directions WHERE (destination_id = 10); 
+-----------+ 
| source_id | 
+-----------+ 
|   2 | 
|   8 | 
... 
|  2563 | 
+-----------+ 
341 rows in set (2.13 sec) 

Tôi lưu ý rằng tại sao giai đoạn "gửi dữ liệu" quá chậm và có thể làm gì để thực hiện nhanh. Xin lưu ý tôi đang thực hiện truy vấn này trên dấu nhắc MySQL trên chính máy chủ, vì vậy không thực sự mong đợi nó dành nhiều thời gian trong việc "gửi dữ liệu". Bất kì manh mối nào?

Nếu nó giúp, tôi có 3 trường văn bản trên bảng này, nhưng vì chúng không được chọn, tôi hy vọng chúng không phải là nguyên nhân của sự chậm trễ này.

Truy vấn này chạy hàng nghìn lần mỗi ngày và thực sự không thể chi tiêu 2 giây mỗi lần.

kết quả Profiling:

 
mysql> show profile for query 4; 
+--------------------------------+----------+ 
| Status       | Duration | 
+--------------------------------+----------+ 
| (initialization)    | 0.000003 | 
| checking query cache for query | 0.000051 | 
| checking permissions   | 0.000007 | 
| Opening tables     | 0.000011 | 
| System lock     | 0.000005 | 
| Table lock      | 0.000023 | 
| init       | 0.00002 | 
| optimizing      | 0.00001 | 
| statistics      | 0.00006 | 
| preparing      | 0.000014 | 
| executing      | 0.000005 | 
| Sending data     | 2.127019 | 
| end       | 0.000015 | 
| query end      | 0.000004 | 
| storing result in query cache | 0.000039 | 
| freeing items     | 0.000011 | 
| closing tables     | 0.000007 | 
| logging slow query    | 0.000047 | 
+--------------------------------+----------+ 
18 rows in set (0.00 sec) 

UPDATE: tôi stumbled khi các URL sau đó nói

 
Each time means the time elapsed between the previous event and the new event. So, the line: 
| Sending data | 0.00016800 | 
means that 0.00016800 seconds elapsed between "executing" and "Sending data". It is, it takes 0.00016800 seconds to execute the query. 

http://forums.mysql.com/read.php?24,241461,242012#msg-242012

Ai đó có thể xác nhận?

+7

Những tuyên bố là không đúng sự thật trên trang được liên kết. Nếu bạn thực hiện 'SHOW PROCESSLIST' trong khi truy vấn đang chạy nó sẽ cho thấy rằng truy vấn thực sự ở trạng thái ** Sending data **. (Không phải trong phần trước). - Và vui lòng không ai nói rằng danh sách xử lý đang hiển thị bước * tiếp theo * trong quá trình thực hiện. :) – vbence

+0

@vbence: bạn đã bao giờ thấy một truy vấn mất nhiều hơn một vài người để chạy? Lý thuyết trên có ý nghĩa. –

+0

@ user9111337 Ồ vâng. Báo cáo tổng hợp (GROUP BY) với WHERE caluse thường sẽ dẫn đến các lựa chọn không thể giải quyết bằng cách sử dụng chỉ mục (EXPLAIN ... sẽ nói "SỬ DỤNG WHERE") - nếu bảng đủ lớn, quá trình này có thể mất vài phút. - Báo cáo này được báo cáo như thế nào? Bạn có thể thấy nó cho chính mình bằng cách thử một 'SHOW PROCESSLIST'. – vbence

Trả lời

1

Bạn có các chỉ mục trên bảng này không? Bạn nói nó trả về khoảng 300. Nhưng bao nhiêu nó cần phải tìm kiếm thông qua để tìm thấy những 300?

15

Kế hoạch giải thích thường là nơi tốt nhất để bắt đầu bất cứ khi nào bạn có truy vấn chậm. Để có một thẻ, hãy chạy

DESCRIBE SELECT source_id FROM directions WHERE (destination_id = 10); 

Điều này sẽ hiển thị cho bạn bảng liệt kê các bước cần thiết để thực hiện truy vấn của bạn. Nếu bạn thấy một giá trị lớn trong cột 'hàng' và NULL trong cột 'khóa', điều đó cho biết rằng truy vấn của bạn phải quét một số lượng lớn hàng để xác định xem hàng nào cần trả về.

Trong trường hợp đó, việc thêm chỉ mục trên destination_id sẽ tăng tốc đáng kể truy vấn của bạn, với một số chi phí để chèn và xóa tốc độ (vì chỉ mục cũng sẽ cần được cập nhật).

+10

Mặc dù tôi đồng ý rằng truy vấn GIẢI THÍCH/DESCRIBE là cách tìm cách khắc phục, bạn không thực sự mô tả giai đoạn "gửi dữ liệu" là gì. Xem http://dev.mysql.com/doc/refman/5.0/en/general-thread-states.html –

-2

Truy vấn của bạn chi tiêu 2.127019 đến thực hiện truy vấn. Điều này có thể do bạn có một lượng lớn dữ liệu và bạn đang thiếu chỉ mục trên cột destination_id. Hãy thử:

TẠO INDEX index_destination_id TRÊN chỉ đường (destination_id);

Sau đó, yêu cầu của bạn sẽ chạy trơn tru.

+3

Tuyên bố này là FALSE xem nhận xét của tôi về câu hỏi. – vbence

+0

Nhưng đối với tôi, trong một kịch bản khác, trên thực tế việc thêm một chỉ mục giải quyết truy vấn chậm của tôi - đôi khi hiển nhiên bị bỏ qua. –

6

Bạn có thể xem phần cứng của máy chủ mysql. Như Mysql doc nói:

gửi dữ liệu

Các chủ đề đang đọc và các hàng gia công cho một câu lệnh SELECT, và gửi dữ liệu cho khách hàng. Bởi vì các hoạt động xảy ra trong trạng thái này có xu hướng thực hiện một lượng lớn truy cập đĩa (đọc), nó thường là trạng thái chạy dài nhất trong suốt thời gian tồn tại của một truy vấn đã cho.

Vì vậy, nếu máy chủ của bạn có đĩa chậm I/O do tệp db/bảng lớn hoặc bảng điều khiển bị vô hiệu hóa InnoDB tùy chọn/phân mảnh/quá trình khởi động RAID/đĩa không chính xác được khởi động (chờ đĩa sớm chết)/bất kỳ lý do của ổ đĩa I/O chậm - nó có thể là lý do cho tăng đáng kể "Gửi dữ liệu" bước như ở máy chủ giai đoạn này thu thập tất cả các dữ liệu yêu cầu từ đĩa và gửi nó cho khách hàng.

Tất nhiên bạn nên cố gắng tối ưu hóa chọn để sử dụng chỉ mục trước và đảm bảo đây không phải là vấn đề lập trình vì điều này ảnh hưởng đến giai đoạn này trong hầu hết các trường hợp.

0

tôi đã cùng một vấn đề: Gửi dữ liệu rất chậm, nhưng tôi đã có chỉ số chính xác, vv

Sau nhiều đào bới xung quanh, tôi thấy rằng join tôi đã so sánh hai lĩnh vực đã được lập chỉ mục, nhưng có khác nhau Collation - một là latin1_swedish_ci và một là uft8_general_ci.

Khi tôi đã gửi cho họ cả hai để utf8 truy vấn là nhanh hơn đáng kể (từ 2,7 giây để 0,002 giây)

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