2012-09-19 27 views
5

Tôi có một loại câu hỏi "khó hiểu" ... nhưng, tôi muốn ném nó ra vì có một chút khác biệt so với bất kỳ thứ gì tôi đã đọc stackoverflow.Làm cách nào để biết liệu bản ghi đã thay đổi trong Postgres

Sự cố cơ bản.

Tôi đang làm việc để chuyển từ mysql sang PostgreSQL 9.1.5 (được lưu trữ trên Heroku). Là một phần trong đó, tôi cần nhập nhiều tệp CSV hàng ngày. Một số dữ liệu là thông tin bán hàng và gần như được đảm bảo là mới và cần được chèn vào. Tuy nhiên, các phần khác của dữ liệu gần như được đảm bảo giống nhau. Ví dụ: tệp csv (lưu ý số nhiều) sẽ có thông tin POS (điểm bán hàng) trong đó. Điều này hiếm khi thay đổi (và rất có thể chỉ thông qua bổ sung). Sau đó, có thông tin sản phẩm. Có khoảng 10.000 sản phẩm (phần lớn sẽ không thay đổi, nhưng có thể có cả bổ sung và cập nhật).

Mục cuối cùng (nhưng quan trọng), là tôi có yêu cầu để có thể cung cấp đường dẫn/thông tin kiểm tra cho bất kỳ mục cụ thể nào. Ví dụ, nếu tôi thêm một bản ghi POS mới, tôi cần có khả năng theo dõi lại tệp mà nó được tìm thấy. Nếu tôi thay đổi mã UPC hoặc mô tả sản phẩm, thì tôi cần có khả năng theo dõi nó trở lại vào tệp nhập (và tệp) nơi thay đổi đến từ đó.

Giải pháp mà tôi đang dự tính.

Vì dữ liệu được cung cấp cho tôi qua CSV nên tôi đang làm việc xung quanh ý tưởng rằng COPY sẽ là cách tốt nhất/nhanh nhất. Cấu trúc của dữ liệu trong các tệp không chính xác những gì tôi có trong cơ sở dữ liệu (tức là đích đến cuối cùng). Vì vậy, tôi sao chép chúng vào các bảng trong lược đồ dàn xếp phù hợp với CSV (lưu ý: một lược đồ trên mỗi nguồn dữ liệu). Các bảng trong lược đồ dàn dựng sẽ có hàng chèn trước khi kích hoạt. Những trình kích hoạt này có thể quyết định phải làm gì với dữ liệu (chèn, cập nhật hoặc bỏ qua).

Đối với các bảng có nhiều khả năng chứa dữ liệu mới, sau đó nó sẽ cố gắng chèn đầu tiên. Nếu bản ghi đã có sẵn, thì nó sẽ trả về NULL (và dừng chèn vào bảng dàn). Đối với các bảng hiếm khi thay đổi, thì nó sẽ truy vấn bảng và xem liệu bản ghi có được tìm thấy hay không. Nếu có, thì tôi cần một cách để xem liệu có bất kỳ trường nào bị thay đổi hay không. (bởi vì hãy nhớ, tôi cần phải chứng minh rằng bản ghi đã được sửa đổi bằng cách nhập khẩu x từ tập tin y) Tôi rõ ràng có thể chỉ cần tấm hơi ra mã và kiểm tra từng cột. Nhưng, đang tìm kiếm một cái gì đó nhiều hơn một chút "hùng hồn" và dễ bảo trì hơn thế.

Nói cách khác, những gì tôi đang làm là kết hợp hệ thống nhập với hệ thống đường mòn kiểm toán. Vì vậy, trong nghiên cứu những con đường mòn kiểm toán, tôi đã xem xét bài viết wiki.postgresql.org sau đây. Có vẻ như hstore có thể là một cách hay để nhận các thay đổi (và có thể dễ dàng bỏ qua một số cột trong bảng không quan trọng - ví dụ: "last_modified")

Tôi chắc chắn sẽ có khoảng 90% công việc ... Tôi đã tạo ra một số bảng thử nghiệm vv và chơi xung quanh với nó.

Câu hỏi của tôi?

Là cách tốt hơn, dễ bảo trì hơn để hoàn thành nhiệm vụ tìm kiếm 3 bản ghi trong số 10K yêu cầu thay đổi cơ sở dữ liệu. Tôi chắc chắn có thể viết một kịch bản python (hoặc cái gì khác) mà đọc các tập tin và cố gắng tìm ra những gì để làm với mỗi bản ghi, nhưng điều đó cảm thấy khủng khiếp không hiệu quả và sẽ dẫn đến rất nhiều chuyến đi vòng.

Một vài điều cuối cùng:

  1. Tôi không có quyền kiểm soát các tập tin đầu vào. Tôi rất thích nó nếu họ chỉ gửi cho tôi những đồng bằng, nhưng họ không và nó hoàn toàn nằm ngoài tầm kiểm soát hoặc ảnh hưởng của tôi.
  2. hệ thống của anh ấy đang phát triển và các nguồn dữ liệu mới có thể được thêm vào sẽ làm tăng đáng kể lượng dữ liệu đang được xử lý (vì vậy, tôi đang cố giữ mọi thứ hiệu quả)
  3. Tôi biết điều này không tốt, đơn giản SO (như "cách sắp xếp danh sách trong python") nhưng tôi tin rằng một trong những điều tuyệt vời về SO là bạn có thể đặt câu hỏi khó và mọi người sẽ chia sẻ suy nghĩ của họ về cách họ nghĩ cách tốt nhất để giải quyết nó.
+0

Hai câu hỏi cuối cùng: 1) bạn có xóa hay là đầu vào "gia tăng"? 2) có thể các nhà cung cấp của các garantee dữ liệu * phím ổn định * (không có cập nhật quan trọng)? – wildplasser

+0

Nó khác với nguồn dữ liệu và loại dữ liệu. Đó chắc chắn là một tình huống mà tôi có lẽ nên ở "phòng thủ" khi xử lý dữ liệu và chuẩn bị cho mọi thứ.Điều đó nói rằng, tôi nghĩ rằng tôi có thể có deletes (nhưng, hiếm) và tôi tin rằng các phím * nên * được ổn định (nói cách khác, ID cho hồ sơ POS nên giữ nguyên giữa tải lên). –

Trả lời

7

Tôi có nhiều hoạt động tương tự. Những gì tôi làm là COPY để bảng dàn tạm:

CREATE TEMP TABLE target_tmp AS 
SELECT * FROM target_tbl LIMIT 0; -- only copy structure, no data 

COPY target_tmp FROM '/path/to/target.csv'; 

Đối hiệu suất, chạy ANALYZE - temp. bảng không được phân tích bằng autovacuum!

ANALYZE target_tmp; 

Ngoài ra để thực hiện, thậm chí có thể tạo chỉ mục hoặc hai trên bảng tạm thời hoặc thêm khóa chính nếu dữ liệu cho phép.

ALTER TABLE ADD CONSTRAINT target_tmp_pkey PRIMARY KEY(target_id); 

Bạn không cần công cụ hiệu suất cho hàng nhập khẩu nhỏ.

Sau đó, sử dụng phạm vi đầy đủ của các lệnh SQL để phân tích dữ liệu mới.
Ví dụ, nếu khóa chính của bảng mục tiêu là target_id ..

lẽ DELETE gì là không có nữa?

DELETE FROM target_tbl t 
WHERE NOT EXISTS (
    SELECT 1 FROM target_tmp t1 
    WHERE t1.target_id = t.target_id 
); 

Sau đó UPDATE những gì sẵn có:

UPDATE target_tbl t 
SET col1 = t1.col1 
FROM target_tmp t1 
WHERE t.target_id = t1.target_id 

Để tránh trống cập nhật, chỉ cần thêm:

... 
AND col1 IS DISTINCT FROM t1.col1; -- repeat for relevant columns 

Hoặc, nếu toàn bộ hàng là có liên quan:

... 
AND t IS DISTINCT FROM t1;   -- check the whole row 

Sau đó INSERT gì mới:

INSERT INTO target_tbl(target_id, col1) 
SELECT t1.target_id, t1.col1 
FROM target_tmp t1 
LEFT JOIN target_tbl t USING (target_id) 
WHERE t.target_id IS NULL; 

Dọn dẹp nếu phiên của bạn đi trên (bảng tạm thời được giảm vào cuối phiên giao dịch tự động):

DROP TABLE target_tmp; 

Hoặc sử dụng ON COMMIT DROP hoặc tương tự với CREATE TEMP TABLE.
Mã chưa được kiểm tra, nhưng phải hoạt động trong bất kỳ phiên bản PostgreSQL hiện đại nào ngoại trừ lỗi chính tả.

+0

Cảm ơn bạn đã trả lời. Ví dụ/chi tiết tốt; Tôi chắc chắn điều này sẽ giúp một số người. Và nó rất gần với những gì tôi cần làm. Một trong những yêu cầu đó là nhận được tôi là theo dõi theo dõi nhập khẩu "lô id" thực sự thay đổi kỷ lục. Nói cách khác, tôi không muốn luôn luôn phải qua/làm mới bản ghi nếu nó tồn tại - chỉ cập nhật nếu có thay đổi. Tôi cho là tôi có thể. Và sau đó chỉ cần có một kích hoạt cập nhật trên bảng và tìm ra có nếu hồ sơ thực sự thay đổi ... nếu có, sau đó thêm một bản ghi kiểm toán đường mòn. Có vẻ hợp lý? Có một cách tốt hơn? –

+0

@DavidS: Điều này có thể đơn giản hơn bạn mong đợi. Tôi đã thêm một chút vào phần UPDATE. Nó luôn luôn là một ý tưởng tốt để loại trừ các bản cập nhật sản phẩm nào. Nếu bạn cần một đường mòn kiểm toán, tôi khuyên bạn nên sao chép các phiên bản lỗi thời (dấu thời gian cộng) vào một bảng lịch sử trước khi bạn 'DELETE' /' UPDATE'. –

+0

đề xuất tốt và cảm ơn bạn đã cập nhật câu trả lời. Đối với mục đích kiểm toán, bạn có muốn sao chép vào bảng lưu trữ (bản sao đầy đủ của dữ liệu + dấu thời gian) chỉ bằng cách sử dụng hstore (x. *) Và lưu trữ nó trong trường văn bản trong bảng loại audit_trail/lịch sử không? Ưu điểm chính của bảng lưu trữ là nó dễ dàng truy vấn. Ưu điểm chính của cách tiếp cận hstore dường như linh hoạt nếu lược đồ của bạn thay đổi trên đường. Tôi biết nó là một chủ đề khá ít và có lẽ có thể là một câu hỏi của riêng nó, nhưng tò mò với suy nghĩ của bạn. Cảm ơn! –

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