2010-01-25 22 views
6

Tôi có một bảng oracle với số lượng kỷ lục 99896618.Oracle & Pagination

tôi cần phải lấy đoạn nhỏ dữ liệu (cho phép nói 100 hồ sơ) để hiển thị nó trên một trang web, (Trong thế giới web chúng tôi gọi nó phân trang). Hiện tại tôi đang sử dụng truy vấn sau để thực hiện điều đó tuy nhiên người dùng không hài lòng với hiệu suất.

SELECT * FROM (select rownum rnum,f.* from findings f where rownum<90000100) 
        WHERE rnum > 90000000 

Hiện tại, đang mất 1 phút 22 giây để nhận kết quả. Có anyway để làm cho nó tốt hơn. Tôi chắc chắn mở cho bất kỳ loại đề xuất nào bao gồm sửa đổi cấu trúc bảng hoặc như thêm các chỉ mục.

(Just FYI, tôi đang sử dụng ASP.NET như công nghệ web phía máy chủ và ADO.NET như lớp truy cập dữ liệu và Silverlight để trình bày phía khách hàng)

Trả lời

6

Truy vấn của bạn sẽ cần phải đếm các bản ghi 90M đầu tiên để nhận được 100 tiếp theo, do đó, hầu như không có chỗ để cải thiện.

Tôi không thấy mệnh đề ORDER BY trong truy vấn con của bạn, nhưng có thể bạn có nó. Trong trường hợp này, bạn có thể muốn tạo chỉ mục trên đó.

Và câu hỏi: người dùng của bạn có thực sự nhấp qua 900K trang trước khi khiếu nại về hiệu suất không?

Cập nhật:

Nếu bạn cần trang mới nhất, bạn cần phải viết lại cột ORDER BY của bạn trong thứ tự giảm dần:

SELECT * 
FROM (
     SELECT rownum rnum, f.* 
     FROM findings f 
     ORDER BY 
       record_ordering_column DESC 
     ) 
WHERE rnum > 900 
     AND rownum <= 100 

và tạo một chỉ mục trên record_ordering_column

Lưu ý rằng tôi trộn rownum từ các truy vấn lồng nhau để cải thiện hiệu suất.

Xem bài viết này trong blog của tôi để xem chi tiết hơn:

+0

Tôi đã tạo số trang dễ dàng bằng cách tạo danh sách thả xuống số trang (chỉ cần mô tả đơn giản, tôi đã tạo điều khiển tùy chỉnh để họ có thể truy cập 1000 trang dễ dàng nhất). Có thể đây là thông tin hữu ích, phần lớn thời gian (khoảng 95% thời gian) người dùng quan tâm đến các bản ghi (mới nhất) cuối cùng. – funwithcoding

1

Nếu bạn sẵn sàng để sửa đổi các bảng tôi sẽ đề nghị bạn thêm một cột rownumber vào bảng (sử dụng trình kích hoạt chèn và một chuỗi để đặt nó) và sau đó bạn thêm chỉ mục vào cột đó.

+0

Không có chỉ mục không nhóm hoặc nhóm trong Oracle - chúng chỉ được gọi là chỉ mục. –

+0

'@OMG Ngựa vằn: có, nhưng có các cụm được lập chỉ mục trong' Oracle'! :) – Quassnoi

+0

@OMG Ngựa vằn: Khóa chính là chỉ mục nhóm trong oracle và tất cả các chỉ mục khóa chính đều không được nhóm. Bạn phải nói về từ khóa 'nonclustered' * mà tôi biết không tồn tại trong oracle. –

5

Từ một trong những bình luận của bạn:

hầu hết thời gian (khoảng 95% thời gian) người dùng quan tâm đến hồ sơ (mới nhất) mới nhất

Trong trường hợp đó, tại sao không hiển thị các bản ghi theo thứ tự ngược lại để 95% thời gian người dùng quan tâm đến trang 1 chứ không phải trang 900.000?

Nếu sau đó thực sự muốn xem "trang 900.000", điều đó có nghĩa là họ quan tâm đến dữ liệu từ một thời gian dài trước đây, vì vậy, cho phép họ lọc dữ liệu bằng cách, ví dụ: phạm vi ngày. Chỉ cần phân trang qua 100 triệu hàng mà không có bất kỳ bộ lọc nào sẽ không bao giờ được thực hiện.

0

Bạn có thực sự cần lấy lại toàn bộ hàng không?Vì điều này có nghĩa là bạn không sử dụng bất kỳ chỉ mục nào.

Nếu bạn vẫn cần nhận toàn bộ hàng. Sử dụng các mô hình sau:

SELECT * FROM findings f1 WHERE f1.rowid IN 
    (SELECT rownum rnum, row_id 
     FROM (
      SELECT f.rowid row_id 
       FROM findings f 
      ORDER BY record_ordering_column 
      ) 
    WHERE rownum > 900 
    ) 
WHERE rnum <= 100; 

Xem

Lưu ý: tinh tế khoản phụ CHỌN cũng như sử dụng các truy vấn ROWID.

Nếu bạn thêm chỉ mục vào record_ordering_column, khi đó, cách dịch sẽ sử dụng chỉ mục để nhận tập hợp ROWID. Sau đó, chỉ tải các khối có chứa các hàng được xác định bởi ROWID của chúng.

Điều này sẽ tốt hơn truy vấn hiện tại của bạn sẽ là quét toàn bộ bảng.