2012-10-30 37 views
11

Theo dõi từ câu hỏi trước đây của tôi:Cách cung cấp ứng dụng khách API với 1.000.000 kết quả cơ sở dữ liệu?

Using "Cursors" for paging in PostgreSQL

một cách tốt để cung cấp một ứng dụng API với 1.000.000 kết quả cơ sở dữ liệu là gì?

Hiện tại, chúng tôi đang sử dụng PostgreSQL. Một vài phương pháp đề nghị:

  • Paging sử dụng Cursors
  • Paging sử dụng số ngẫu nhiên (Add "LỚN HƠN ORDER BY" cho mỗi truy vấn)
  • Paging sử dụng LIMIT và OFFSET (bị phá vỡ cho các tập dữ liệu rất lớn)
  • Lưu thông tin vào một tập tin và để cho các khách hàng tải nó
  • Duyệt qua kết quả, sau đó POST dữ liệu đến máy chủ của khách hàng
  • Return chỉ phím cho khách hàng, sau đó cho phép các khách hàng requ est các đối tượng từ các tập tin đám mây như Amazon S3 (vẫn có thể yêu cầu phân trang chỉ để có được tên tập tin).

Tôi chưa nghĩ gì về điều đó đơn giản ngớ ngẩn và tốt hơn bất kỳ tùy chọn nào trong số này?

Trả lời

24

Bảng có khóa chính. Hãy tận dụng nó.

Thay vì LIMITOFFSET, hãy phân trang với bộ lọc trên khóa chính. Bạn ám chỉ này với bình luận của bạn:

Paging sử dụng số ngẫu nhiên (Add "LỚN HƠN ORDER BY" cho mỗi truy vấn )

nhưng không có gì ngẫu nhiên về cách bạn nên làm điều đó cả.

SELECT * FROM big_table WHERE id > $1 ORDER BY id ASC LIMIT $2 

Cho phép khách hàng chỉ định cả thông số, ID cuối cùng mà số lần xem và số lượng bản ghi để tìm nạp. API của bạn sẽ phải có trình giữ chỗ, thông số bổ sung hoặc cuộc gọi thay thế cho "tìm nạp các ID đầu tiên n" nơi nó bỏ qua mệnh đề WHERE từ truy vấn, nhưng điều đó không quan trọng.

Cách tiếp cận này sẽ sử dụng quét chỉ mục khá hiệu quả để lấy các bản ghi theo thứ tự, thường tránh bị sắp xếp hoặc cần phải lặp qua tất cả các bản ghi bị bỏ qua. Khách hàng có thể quyết định có bao nhiêu hàng nó muốn cùng một lúc.

Cách tiếp cận này khác với cách tiếp cận LIMITOFFSET theo một cách chính: sửa đổi đồng thời.Nếu bạn INSERT vào bảng có khóa thấp hơn so với khóa mà một số khách hàng đã thấy, phương pháp này sẽ không thay đổi kết quả của nó, trong khi cách tiếp cận OFFSET sẽ lặp lại một hàng. Tương tự, nếu bạn DELETE một hàng có ID thấp hơn đã thấy, kết quả của phương pháp này sẽ không thay đổi, trong khi OFFSET sẽ bỏ qua hàng không nhìn thấy. Mặc dù vậy, không có sự khác biệt nào cho các bảng chỉ nối thêm với các khóa được tạo ra.

Nếu bạn biết trước rằng khách hàng sẽ muốn toàn bộ kết quả, điều hiệu quả nhất cần làm là chỉ gửi cho họ toàn bộ kết quả được đặt không có doanh nghiệp phân trang này. Đó là nơi tôi sẽ sử dụng con trỏ. Đọc các hàng từ DB và gửi chúng cho khách hàng nhanh như khách hàng sẽ chấp nhận chúng. API này sẽ cần phải đặt giới hạn về mức độ chậm của khách hàng được cho phép để tránh tải phụ trợ quá mức; cho một khách hàng chậm tôi có thể chuyển sang phân trang (như mô tả ở trên) hoặc spool toàn bộ con trỏ kết quả ra một tập tin tạm thời và đóng kết nối DB.

hãy cẩn thận quan trọng:

  • Yêu cầu UNIQUE chế/UNIQUE index hoặc PRIMARY KEY là đáng tin cậy
  • khác nhau hành vi đồng thời sửa đổi để hạn chế/bù đắp, xem ở trên
1

Yêu cầu API chấp nhận bù đắp để bắt đầu và số lượng hồ sơ cần trả lại. Đây là một loại phân trang nơi khách hàng có thể xác định số lượng bản ghi để trả lại trong một yêu cầu trang. API cũng sẽ trả lại tổng số bản ghi có thể cho truy vấn để khách hàng biết số lượng "trang" hoặc tùy chọn có thể lấy được khi nó đã truy xuất các bản ghi cuối cùng khi số lượng bản ghi được trả về bằng 0 hoặc nhỏ hơn số hồ sơ được yêu cầu. Bạn có thể kiểm soát điều này trong truy vấn PostgresSQL của bạn bằng cách sử dụng mệnh đề OFFSET (bản ghi nào để bắt đầu truy xuất tại) và mệnh đề LIMIT (số bản ghi để trả về) trong câu lệnh SELECT của bạn.

+3

Vấn đề với việc sử dụng OFFSET là nó yêu cầu máy chủ lặp lại toàn bộ tập kết quả trước "LIMIT", vì vậy nó phân tích cho các tập dữ liệu rất lớn. Tôi đã thực sự sử dụng một API đã làm điều này và chúng tôi đã gặp phải các vấn đề lớn khi nhận được dữ liệu sau khoảng 100.000 kết quả. –

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