Lưu trữ hình ảnh trong PostgreSQL


111

Được rồi, vì vậy tôi đang làm việc trên một ứng dụng sẽ sử dụng phần mềm hỗ trợ Linux chạy PostgreSQL để cung cấp hình ảnh cho hộp Windows với giao diện người dùng được viết bằng C # .NET, mặc dù giao diện người dùng hầu như không quan trọng. Câu hỏi của tôi là:

  • Cách tốt nhất để giải quyết việc lưu trữ hình ảnh trong Postgres là gì?

Mỗi hình ảnh có kích thước khoảng 4-6 megapixel và chúng tôi đang lưu trữ lên tới 3000. Cũng có thể tốt cần lưu ý: đây không phải là một ứng dụng web, nhiều nhất sẽ có khoảng hai front-end truy cập cơ sở dữ liệu cùng một lúc.

Câu trả lời:


64

Cập nhật đến năm 2012, khi chúng ta thấy rằng kích thước hình ảnh và số lượng hình ảnh đang ngày càng tăng lên trong tất cả các ứng dụng ...

Chúng tôi cần một số phân biệt giữa "hình ảnh gốc" và "hình ảnh đã xử lý", như hình thu nhỏ.

Như câu trả lời của Jcoby nói, có hai lựa chọn, do đó, tôi khuyên bạn nên:

  • sử dụng blob (Binary Large OBject): để lưu trữ hình ảnh gốc, tại bàn của bạn. Xem câu trả lời của Ivan (không có vấn đề gì với việc sao lưu các đốm màu!), Các mô-đun được cung cấp bổ sung của PostgreSQL , Hướng dẫn thực hiện, v.v.

  • sử dụng cơ sở dữ liệu riêng với DBlink : cho kho ảnh gốc, tại cơ sở dữ liệu (thống nhất / chuyên biệt) khác. Trong trường hợp này, tôi thích bytea hơn , nhưng blob gần giống nhau. Tách cơ sở dữ liệu là cách tốt nhất cho một "dịch vụ web hình ảnh hợp nhất".

  • sử dụng bytea (Mảng BYTE): để lưu vào bộ nhớ đệm hình ảnh thu nhỏ. Lưu vào bộ nhớ cache các hình ảnh nhỏ để gửi nó nhanh đến trình duyệt web (để tránh các sự cố hiển thị) và giảm quá trình xử lý của máy chủ. Bộ nhớ cache cũng là siêu dữ liệu cần thiết, như chiều rộng và chiều cao. Bộ nhớ đệm cơ sở dữ liệu là cách dễ nhất, nhưng hãy kiểm tra nhu cầu của bạn và cấu hình máy chủ (ví dụ: mô-đun Apache): lưu trữ hình thu nhỏ tại hệ thống tệp có thể tốt hơn, so sánh hiệu suất. Hãy nhớ rằng nó là một dịch vụ web (hợp nhất), sau đó có thể được lưu trữ tại một cơ sở dữ liệu riêng biệt (không có bản sao lưu), phục vụ nhiều bảng. Xem thêm hướng dẫn sử dụng kiểu dữ liệu nhị phân PostgreSQL , kiểm tra với cột bytea , v.v.

LƯU Ý1: ngày nay việc sử dụng "giải pháp kép" (cơ sở dữ liệu + hệ thống tệp) không được dùng nữa (!). Có nhiều lợi ích khi sử dụng "chỉ cơ sở dữ liệu" thay vì kép. PostgreSQL có hiệu suất tương đương và các công cụ tốt để xuất / nhập / nhập / xuất.

LƯU Ý 2: hãy nhớ rằng PostgreSQL chỉ có bytea , không có BLOB mặc định của Oracle : "Chuẩn SQL định nghĩa (...) BLOB. Định dạng đầu vào khác với bytea, nhưng các hàm và toán tử được cung cấp hầu hết giống nhau", Hướng dẫn sử dụng .


CHỈNH SỬA 2014 : Hôm nay tôi không thay đổi văn bản gốc ở trên (câu trả lời của tôi là ngày 22 tháng 4 năm 12, hiện có 14 phiếu bầu), tôi đang mở câu trả lời cho những thay đổi của bạn (xem "Chế độ Wiki", bạn có thể chỉnh sửa!), Để hiệu đínhđể cập nhật .
Câu hỏi ổn định (câu trả lời '08 của @ Ivans với 19 phiếu bầu), vui lòng giúp cải thiện văn bản này.


2
Tham chiếu cho "... việc sử dụng" giải pháp kép "(cơ sở dữ liệu + hệ thống tệp) không được chấp nhận là gì ..."?
dangel 10/02/19

Một số tin tức năm 2019! Kể từ năm 2018, PostgREST hỗ trợ đầu ra trực tiếp của bytea lên web. Xem cấu hình NGINX đơn giản này để sử dụng nó. Xem Hướng dẫn PostgREST về đầu ra nhị phân
Peter Krauss

52

Câu trả lời của Re jcoby:

bytea là cột "bình thường" cũng có nghĩa là giá trị được đọc hoàn toàn vào bộ nhớ khi bạn tìm nạp nó. Ngược lại, các khối màu, bạn có thể truyền vào stdout. Điều đó giúp giảm dung lượng bộ nhớ máy chủ. Đặc biệt, khi bạn lưu trữ hình ảnh 4-6 MPix.

Không có vấn đề gì với việc sao lưu các đốm màu. pg_dump cung cấp tùy chọn "-b" để đưa các đối tượng lớn vào bản sao lưu.

Vì vậy, tôi thích sử dụng pg_lo_ * hơn, bạn có thể đoán.

Câu trả lời của Kris Erickson:

Tôi sẽ nói ngược lại :). Khi hình ảnh không phải là dữ liệu duy nhất bạn lưu trữ, đừng lưu trữ chúng trên hệ thống tệp trừ khi bạn hoàn toàn phải làm như vậy. Đó là một lợi ích khi luôn chắc chắn về tính nhất quán dữ liệu của bạn và có dữ liệu "trong một phần" (DB). BTW, PostgreSQL rất tốt trong việc duy trì tính nhất quán.

Tuy nhiên, đúng, thực tế thường quá đòi hỏi hiệu suất ;-), và nó thúc đẩy bạn phân phát các tệp nhị phân từ hệ thống tệp. Nhưng ngay cả khi đó tôi vẫn có xu hướng sử dụng DB làm bộ lưu trữ "chính" cho các tệp nhị phân, với tất cả các mối quan hệ khác được liên kết nhất quán, đồng thời cung cấp một số cơ chế lưu trữ dựa trên hệ thống tệp để tối ưu hóa hiệu suất.


14
Sau 10 năm, bạn có nghĩ rằng số điểm của bạn vẫn còn giá trị? Bất kỳ cập nhật nào kể từ đó?
leventunver

3
@leventunver Không, những điểm không nên giữ. Ví dụ đầu tiên về việc BYTEAlà một cột "bình thường". Postgres đã hỗ trợ truyền trực tuyến đến / từ BYTEAcác cột trong nhiều năm, có nghĩa là bạn không cần phải lưu trữ nội dung trong bộ nhớ trước khi lưu trữ trong db.
oligofren

29

Trong cơ sở dữ liệu, có hai tùy chọn:

  • tạm biệt. Lưu trữ dữ liệu trong một cột, được xuất như một phần của bản sao lưu. Sử dụng các chức năng cơ sở dữ liệu tiêu chuẩn để lưu và truy xuất. Đề xuất cho nhu cầu của bạn.
  • đốm màu. Lưu trữ dữ liệu bên ngoài, không được xuất thông thường như một phần của bản sao lưu. Yêu cầu các chức năng cơ sở dữ liệu đặc biệt để lưu và truy xuất.

Trước đây, tôi đã sử dụng cột bytea rất thành công khi lưu trữ hơn 10 gb hình ảnh với hàng nghìn hàng. Chức năng TOAST của PG phủ nhận khá nhiều lợi thế mà các đốm màu có. Bạn sẽ cần bao gồm các cột siêu dữ liệu trong cả hai trường hợp cho tên tệp, loại nội dung, kích thước, v.v.


1
10GB không phải là nhiều :-( Tôi đang tìm giải pháp TBS
Valentin Heinitz

2
@ValentinHeinitz Đối với TB, Postgres vani vẫn gặp khó khăn ngay cả với các cột văn bản nhỏ hơn.
sudo

23

Cập nhật nhanh đến giữa năm 2015:

Bạn có thể sử dụng giao diện Dữ liệu nước ngoài Postgres , để lưu trữ tệp trong cơ sở dữ liệu phù hợp hơn. Ví dụ: đặt các tệp trong GridFS là một phần của MongoDB. Sau đó, sử dụng https://github.com/EnterpriseDB/mongo_fdw để truy cập nó trong Postgres.

Điều đó có lợi thế là bạn có thể truy cập / đọc / ghi / sao lưu nó trong Postrgres và MongoDB, tùy thuộc vào những gì mang lại cho bạn khả năng linh hoạt hơn.

Ngoài ra còn có các trình bao bọc dữ liệu nước ngoài cho các hệ thống tệp: https://wiki.postgresql.org/wiki/Foreign_data_wrappers#File_Wrappers

Ví dụ, bạn có thể sử dụng cái này: https://multicorn.readthedocs.org/en/latest/foreign-data-wrappers/fsfdw.html (xem ở đây để biết ví dụ sử dụng ngắn gọn)

Điều đó mang lại cho bạn lợi thế về tính nhất quán (tất cả các tệp được liên kết chắc chắn ở đó) và tất cả các ACID khác, trong khi vẫn còn trên hệ thống tệp thực tế, có nghĩa là bạn có thể sử dụng bất kỳ hệ thống tệp nào bạn muốn và máy chủ web có thể phục vụ chúng trực tiếp ( Bộ nhớ đệm hệ điều hành cũng áp dụng).


1
Cảm ơn .. Trình bao bọc dữ liệu nước ngoài (file_fdw) có cung cấp quyền ghi cho hình ảnh không? Tôi muốn lưu trữ hình ảnh vào FileSystem và siêu dữ liệu của nó trong Postgresql, nhưng tôi cũng phải duy trì tính nhất quán. Bạn có một giải pháp chi tiết? Có tiện ích mở rộng nào khác không? Multicorn cần python và tôi muốn phải làm mà không sử dụng Python ..
Jay Khatwani

1
Có, họ có quyền ghi. Chúng hoàn toàn nhất quán từ / theo cả hai hướng. Và không, tôi không biết một giải pháp bình đẳng thực hiện điều này mà không cần python.
Kenyakorn Ketsombut

18

Cập nhật từ 10 năm sau Vào năm 2008, các ổ cứng mà bạn sử dụng cơ sở dữ liệu sẽ có nhiều đặc điểm khác nhau và giá thành cao hơn nhiều so với các ổ đĩa mà bạn sẽ lưu trữ các tệp trên đó. Ngày nay, có nhiều giải pháp tốt hơn để lưu trữ các tệp không tồn tại 10 năm trước và tôi sẽ rút lại lời khuyên này và khuyên độc giả xem một số câu trả lời khác trong chủ đề này.

Nguyên

Đừng lưu trữ hình ảnh trong cơ sở dữ liệu trừ khi bạn hoàn toàn phải làm như vậy. Tôi hiểu rằng đây không phải là một ứng dụng web, nhưng nếu không có vị trí tệp được chia sẻ mà bạn có thể trỏ để lưu vị trí của tệp trong cơ sở dữ liệu.

//linuxserver/images/imagexxx.jpg

thì có lẽ bạn có thể nhanh chóng thiết lập một máy chủ web và lưu trữ các url web trong cơ sở dữ liệu (cũng như đường dẫn cục bộ). Mặc dù cơ sở dữ liệu có thể xử lý LOB và 3000 hình ảnh (4-6 Megapixel, giả sử 500K một hình ảnh) 1,5 Gigs không phải là nhiều hệ thống tệp không gian được thiết kế tốt hơn nhiều để lưu trữ các tệp lớn hơn so với cơ sở dữ liệu.


15
Nhưng bạn phải nghĩ ra một cách để phân phối các tệp trên một số thư mục. Hệ thống tập tin không phải là tốt tại lưu trữ triệu tập tin trong một đơn thư (hàng ngàn thực sự mười đã là một vấn đề)
a_horse_with_no_name

1
Không trả lời câu hỏi ban đầu. Cá nhân tôi muốn lưu trữ hình ảnh trong Postgres chỉ vì tôi muốn SQL làm lớp trừu tượng của mình và cũng không muốn quản lý các tệp trong hệ thống tệp ext4 của mình.
sudo

Tôi mâu thuẫn, điều này không trả lời được câu hỏi, nhưng tôi đã ủng hộ nó, bởi vì nó là một câu trả lời tốt hơn một câu trả lời cho câu hỏi.
Andrew Carr

6

Hãy thử điều này . Tôi đã sử dụng định dạng Large Object Binary (LOB) để lưu trữ các tài liệu PDF đã tạo, một số trong số đó có kích thước trên 10 MB, trong cơ sở dữ liệu và nó hoạt động tuyệt vời.


2

Nếu hình ảnh của bạn nhỏ, hãy cân nhắc lưu trữ chúng dưới dạng base64 trong trường văn bản thuần túy.

Lý do là mặc dù base64 có tổng chi phí là 33%, nhưng việc nén gần như biến mất. (Xem Chi phí không gian của mã hóa Base64 là gì? ) Cơ sở dữ liệu của bạn sẽ lớn hơn, nhưng các gói tin mà máy chủ web của bạn gửi đến máy khách sẽ không có. Trong html, bạn có thể nội tuyến base64 trong thẻ <img src = "">, điều này có thể đơn giản hóa ứng dụng của bạn vì bạn sẽ không phải phân phối hình ảnh dưới dạng tệp nhị phân trong một lần tìm nạp trình duyệt riêng biệt. Xử lý hình ảnh dưới dạng văn bản cũng đơn giản hóa mọi thứ khi bạn phải gửi / nhận json, điều này không xử lý nhị phân tốt lắm.

Có, tôi hiểu rằng bạn có thể lưu trữ nhị phân trong cơ sở dữ liệu và chuyển đổi nó thành / từ văn bản trên đường vào và ra khỏi cơ sở dữ liệu, nhưng đôi khi ORM làm điều đó trở nên phức tạp. Có thể đơn giản hơn chỉ cần coi nó là văn bản thẳng giống như tất cả các trường khác của bạn.

Đây chắc chắn là cách phù hợp để xử lý hình thu nhỏ.

(Hình ảnh của OP không nhỏ, vì vậy đây không thực sự là câu trả lời cho câu hỏi của anh ấy.)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.