2008-09-24 23 views
8

Tôi có một tập lệnh SQL mà tôi muốn xuất thông báo tiến trình khi nó chạy. Có thông điệp đầu ra giữa các câu lệnh SQL là dễ dàng, tuy nhiên tôi có một số lệnh INSERT INTO SELECT đang chạy rất dài. Có cách nào để có một thông báo đầu ra lệnh chọn khi nó đi, ví dụ sau mỗi 1000 hàng, hoặc mỗi 5 giây?Làm cách nào để xuất thông báo tiến trình từ câu lệnh SELECT?

Lưu ý: Đây là cho SQL Anywhere, nhưng câu trả lời trong bất kỳ phương ngữ SQL nào cũng sẽ ổn.

Trả lời

3

Bản thân SQL không có điều khoản cho loại điều này. Bất kỳ cách nào để làm điều này sẽ liên quan đến việc nói chuyện trực tiếp với cơ sở dữ liệu, và sẽ không được tiêu chuẩn trên cơ sở dữ liệu.

2

Chắc chắn không có giải pháp chuẩn SQL nào cho điều này. Xin lỗi được doom-laden, nhưng tôi đã không nhìn thấy bất cứ điều gì có thể làm điều này trong Oracle, SQL Server, Sybase hoặc MySQL, vì vậy tôi sẽ không quá hy vọng cho SQLAnywhere.

+0

Oracle có 'v $ session_longops': http://docs.oracle.com/cd/E11882_01/server.112/e25513/dynviews_3022.htm#i1415618 –

0

Khi tắt cơ hội bạn đang sử dụng Toad, bạn có thể tạo tập hợp các câu lệnh INSERT từ một bảng và định cấu hình nó để cam kết với tần suất nhập của người dùng. Bạn có thể sửa đổi kịch bản của bạn một chút và sau đó xem có bao nhiêu dữ liệu mới đã được cam kết khi bạn đi.

+0

Không, không sử dụng Toad. Nếu nó sẽ dễ phân vùng các câu lệnh INSERT thì tôi có thể nhận được một bản cập nhật tiến trình giữa chúng, nhưng điều đó không làm việc cho các câu lệnh INSERT INTO SELECT. –

2

Tôi đồng ý rằng SQL không có cách nào để thực hiện việc này trực tiếp. Một cách có thể là chỉ chèn TOP 1000 cùng một lúc và sau đó in thông điệp trạng thái của bạn. Sau đó, lặp lại điều này khi cần thiết (trong một vòng lặp của một số loại). Nhược điểm là bạn sẽ cần một cách để theo dõi bạn đang ở đâu.

Tôi nên lưu ý rằng phương pháp này sẽ không hiệu quả như chỉ làm một INSERT lớn

+0

đây là cách tôi đã thực hiện nó trước đây. Khẳng định rằng nó là cách chậm hơn. –

+0

Tôi có thể thử một lần nữa. thêm 'where row_id between ...' vào bảng chính trong phần nối, sau đó lặp lại cho mỗi phân vùng. Tôi có thể giải quyết nó chậm hơn một chút, vì vậy chúng tôi sẽ phải xem nó chậm hơn bao nhiêu. –

3

Thật ý tưởng về tiến bộ với các hoạt động dựa trên bộ (đó là những gì một cơ sở dữ liệu quan hệ sử dụng) sẽ không quá hữu ích, ít nhất không được hiển thị với thanh tiến trình (phần trăm được thực hiện so với tổng số). Vào thời điểm người tối ưu hóa tìm ra điều cần làm và thực sự hiểu toàn bộ chi phí hoạt động, bạn đã hoàn thành một phần đáng kể của hoạt động. Hiển thị tiến trình thực sự có nghĩa là cho các hoạt động lặp lại thay vì đặt các hoạt động.

Điều đó nói về việc thực hiện câu lệnh SELECT chung của bạn. Đối với các chèn là các câu lệnh riêng biệt, có tất cả các cách để thực hiện điều đó từ người gửi bằng cách theo dõi tỷ lệ tiêu thụ của các câu lệnh. Nếu chúng được chèn số lượng lớn (chọn vào, chèn từ, và tương tự) thì bạn thực sự có cùng một vấn đề mà tôi đã mô tả ở trên. Các hoạt động thiết lập được sắp xếp theo cách mà làm cho một loại thanh tiến trình hiển thị hơi vô nghĩa.

+0

Hmm, đó là một điểm tốt, tôi đã không nghĩ về nó theo cách đó. –

5

Không có cách nào để truy xuất trạng thái thực hiện của một truy vấn. Không có công cụ cơ sở dữ liệu chủ đạo nào cung cấp chức năng này.
Hơn nữa, chi phí có thể đo lường sẽ được tạo từ bất kỳ quá trình triển khai nào là tồn tại, vì vậy nếu truy vấn đã mất một thời gian dài không thoải mái sao cho bạn muốn hiển thị tiến độ, gây chậm lại bằng cách hiển thị tiến trình nói trên có thể không phải là thiết kế mục tiêu.
Bạn có thể tìm thấy số này article on estimating SQL execution progress hữu ích, mặc dù các hàm ý thực tiễn của nó bị giới hạn.

+0

Cảm ơn bạn đã liên kết, đọc khá thú vị! –

+0

Tôi cũng nghĩ như vậy, nhưng có quá ít lý thuyết đặc biệt hữu ích. Nó quá xấu không có "với số liệu thống kê" loại gợi ý truy vấn trong bất kỳ rdbms chúng ta biết, nhưng suy nghĩ về nó, thực hiện sẽ rất khó khăn và tốn nhiều tài nguyên Tôi đoán nó không đáng ngạc nhiên. – Grank

+0

"* Không có công cụ cơ sở dữ liệu chủ đạo nào cung cấp chức năng này * - điều đó không đúng. Oracle có' v $ session_longops': http://docs.oracle.com/cd/E11882_01/server.112/e25513/dynviews_3022.htm# i1415618 –

3

Tôi đang sử dụng nhóm phát triển động cơ SQL Anywhere và hiện tại không có cách nào để thực hiện việc này. Tôi không thể hứa hẹn bất kỳ điều gì, nhưng chúng tôi đang cân nhắc việc thêm loại chức năng này vào bản phát hành trong tương lai.

0

Bạn có thể mô phỏng hiệu ứng cho người dùng của mình bằng cách định thời gian một số lần chạy, sau đó có thanh tiến trình ở tốc độ trung bình/giây.

duy nhất cách khác sẽ

1 - Tham khảo các API của cơ sở dữ liệu của bạn để xem nếu nó làm cho bất kỳ điều khoản cho rằng

hoặc

2 - Break INSERT của bạn thành nhiều nhỏ báo cáo, và báo cáo về chúng khi bạn đi. Nhưng điều đó sẽ có tác động tiêu cực đáng kể về hiệu suất.

0

Nếu bạn cần phải có nó hoặc bạn chết, cho chèn, cập nhật, xóa, bạn có thể sử dụng một số logic kích hoạt với các biến db, và thời gian bằng thời gian bạn làm sql để lấy dữ liệu biến và hiển thị một số tiến bộ cho người sử dụng.

Nếu bạn không sử dụng, tôi có thể viết một ví dụ và gửi nó.

1

Một ý nghĩ có thể có một quá trình riêng biệt đếm số hàng trong bảng nơi chèn đang được thực hiện để xác định phần trăm trong số đó đã có. Điều này tất nhiên sẽ yêu cầu bạn biết tổng số cuối cùng. Điều này có lẽ sẽ chỉ được okay nếu điều này bạn không quá lo lắng về tải máy chủ.

+0

Giả sử bạn đang sử dụng một dạng axit yếu cho phép bạn thấy kết quả giữa giao dịch sẽ hoạt động, đúng vậy. –

2

Dưới đây là những gì tôi sẽ làm gì (Sybase/SQL Server cú pháp):

DECLARE @total_rows int 

SELECT @total_rows = count(*) 
FROM Source_Table 

WHILE @total_rows > (SELECT count(*) FROM Target_Table) 
BEGIN 
    SET rowcount 1000 

    print 'inserting 1000 rows' 

    INSERT Target_Table   
    SELECT * 
    FROM Source_Table s 
    WHERE NOT EXISTS(SELECT 1 
         FROM Target_Table t 
         WHERE t.id = s.id) 
END 

set rowcount 0 
print 'done' 

Hoặc bạn có thể làm điều đó dựa vào ID (giả định Id là một con số):

DECLARE @min_id int, 
     @max_id int, 
     @start_id int, 
     @end_id int 

SELECT @min_id = min(id) , 
     @max_id = max(id) 
FROM Source_Table 

SELECT @start_id = @min_id , 
     @end_id = @min_id + 1000 

WHILE @end_id <= @max_id 
BEGIN 

    print 'inserting id range: ' + convert(varchar,@start_id) + ' to ' + convert(varchar,@end_id) 

    INSERT Target_Table   
    SELECT * 
    FROM Source_Table s 
    WHERE id   BETWEEN @start_id AND @end_id 

    SELECT @start_id = @end_id + 1, 
      @end_id = @end_id + 1000 
END 

set rowcount 0 
print 'done' 
0

stumbled khi này chủ đề cũ đang tìm kiếm thứ gì đó khác. Tôi không đồng ý với ý tưởng rằng chúng tôi không muốn thông tin tiến bộ chỉ vì nó là một hoạt động được thiết lập. Người dùng sẽ thường chịu đựng ngay cả chờ đợi lâu nếu họ biết nó kéo dài bao lâu.

Đây là những gì tôi đề nghị:

Mỗi lần này chạy, đăng nhập số hàng chèn và tổng thời gian, sau đó thêm một bước vào đầu của quá trình đó để truy vấn log đó và tính toán một tổng thời gian dự kiến. Nếu bạn căn cứ ước tính của mình trong lần chạy cuối cùng, bạn sẽ có thể trình bày một dự đoán tốt có thể chấp nhận được cho thời gian chờ đợi để kết thúc.

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