Làm thế nào để chọn đối chiếu cho cơ sở dữ liệu quốc tế?


22

Tôi đang thiết kế một cơ sở dữ liệu sẽ lưu trữ dữ liệu bằng các ngôn ngữ khác nhau (sử dụng UTF-8), vì vậy tôi nghĩ cách tốt nhất để hiển thị kết quả của truy vấn là sắp xếp nó theo ngôn ngữ của người dùng trong chính truy vấn ( vì có nhiều hơn một cách chính xác để làm điều đó ), như sau:

SELECT a < b COLLATE "de_DE" FROM test1;

Giả sử đây là cách chính xác để làm việc với dữ liệu quốc tế, đó là đối chiếu tốt nhất cho chính cơ sở dữ liệu? Tài liệu PostgreSQL nói :

Cả hai đối chiếu C và POSIX đều chỉ định hành vi "C truyền thống", trong đó chỉ các chữ cái ASCII "A" đến "Z" được coi là các chữ cái và việc sắp xếp được thực hiện nghiêm ngặt theo các giá trị byte mã ký tự.

Tôi nghĩ rằng đây là sự lựa chọn tốt nhất trong trường hợp này, hoặc tôi sai?

(Câu hỏi về phần thưởng: có quá chậm để chọn đối chiếu trong chính truy vấn không?).


2
Điểm đau lớn nhất mà bạn sẽ phải chịu là trong một DB đa ngôn ngữ, bạn cần rất nhiều chỉ mục, vì các chỉ mục trên văn bản có thể đối chiếu là đặc thù đối chiếu. Tuy nhiên, nếu bạn có xu hướng chỉ tìm kiếm trong một đối chiếu / ngôn ngữ đối xứng, bạn có thể sử dụng các chỉ mục một phần để giúp kiểm soát kích thước chỉ mục.
Craig Ringer

2
Khi trích dẫn một nguồn, thêm một liên kết.
Erwin Brandstetter

Câu trả lời:


27

Đối Cchiếu là sự lựa chọn đúng đắn.

Mọi thứ nhanh hơn một chút mà không cần địa phương. Và vì dù sao không có đối chiếu là đúng, hãy tạo cơ sở dữ liệu mà không cần đối chiếu, có nghĩa là với C.

Nó có thể là một nỗi đau khi phải cung cấp một đối chiếu cho nhiều hoạt động. Tuy nhiên, không nên có sự khác biệt đáng chú ý về tốc độ giữa đối chiếu mặc định và đối chiếu đặc biệt. Sau tất cả, đó chỉ là dữ liệu chưa được sắp xếp và quy tắc đối chiếu được áp dụng khi sắp xếp.

Xin lưu ý rằng Postgres xây dựng trên các cài đặt ngôn ngữ được cung cấp bởi HĐH cơ bản, do đó bạn cần phải tạo các địa điểm cho từng miền được sử dụng. Thêm trong câu trả lời liên quan về SO ở đâyở đây .

Tuy nhiên, như @Craig đã đề cập , các chỉ mục là nút cổ chai trong kịch bản này. Đối chiếu của chỉ mục phải khớp với đối chiếu của toán tử được áp dụng trong nhiều trường hợp liên quan đến dữ liệu ký tự.

Bạn có thể sử dụng bộ COLLATExác định trong các chỉ mục để tạo các chỉ mục phù hợp. Các chỉ mục một phần có thể là lựa chọn hoàn hảo nếu bạn trộn dữ liệu trong cùng một bảng.

Ví dụ: bảng có chuỗi quốc tế:

CREATE TABLE string (
   string_id serial
  ,lang_id   int NOT NULL
  ,string    text NOT NULL
);

Và bạn chủ yếu quan tâm đến một ngôn ngữ tại một thời điểm:

SELECT *
FROM   string
WHERE  lang_id = 5  -- 5 being German / Germany here
AND    string > 'foo' COLLATE "de_DE"
ORDER  BY string COLLATE "de_DE";

Sau đó tạo các chỉ mục một phần như:

CREATE INDEX string_string_lang_id_idx ON string (string COLLATE "de_DE")
WHERE lang_id = 5;

Một cho mỗi ngôn ngữ bạn cần.

Trên thực tế, thừa kế có thể là một cách tiếp cận ưu việt cho một bảng như thế này. Sau đó, bạn có thể có một chỉ mục đơn giản trên mỗi bảng được kế thừa chỉ chứa các chuỗi cho một miền địa phương. Tất nhiên, bạn cần phải thoải mái với các quy tắc đặc biệt cho các bảng được kế thừa.


1
Bạn có sử dụng ngôn ngữ C (hoặc 'không phải miền địa phương' để chính xác) theo mặc định cho bất kỳ cơ sở dữ liệu mới nào không?
Jack Douglas

1
@JackDoumund: Không, tôi sẽ chỉ làm điều đó cho những trường hợp đặc biệt. Thông thường, nó thực tế hơn nhiều để làm việc với địa phương thường được sử dụng tại nơi.
Erwin Brandstetter

13

Tôi khuyên bạn nên chọn đối chiếu cung cấp thứ tự Unicode mặc định. Bằng cách đó, bạn sẽ nhận được kết quả lành mạnh ngay cả khi bạn không ghi đè đối chiếu trong mỗi truy vấn. Thật không may, hầu hết (tất cả?) Các hệ điều hành không cung cấp một ngôn ngữ được đặt tên đơn giản là "Unicode mặc định" hoặc một cái gì đó tương tự, vì vậy bạn sẽ phải đoán và / hoặc nghiên cứu một lựa chọn tốt. Ví dụ: trên Linux / glibc, các ngôn ngữ de_DE.utf8 hoặc en_US.utf8 chỉ đơn giản chuyển qua hành vi mặc định, vì vậy cả hai đều là những lựa chọn tốt.

Tôi không nghĩ sử dụng ngôn ngữ C là một ý tưởng hay, bởi vì sau đó hành vi mặc định của ứng dụng của bạn sẽ vô dụng. Và bạn có thể không có hành vi thích hợp từ các hoạt động chuyển đổi trường hợp.

(Ghi đè đối chiếu trong truy vấn không có nhiều chi phí. Đây chỉ là thao tác phân tích cú pháp.)


Có lẽ bớt đau đớn hơn để có một mặc định lành mạnh ..
Erwin Brandstetter

1
Hiện tại tôi đang sử dụng es_CL.utf8 trong cơ sở dữ liệu thử nghiệm, nhưng nhờ câu trả lời của bạn, tôi đã tìm hiểu thêm một chút và thấy rằng đó utf8_unicode_cilà cách để đi .
Tae

0

Chúng tôi sử dụng postgres trong một container docker, do đó chúng tôi luôn có sẵn ICU và sử dụng und-x-iculàm mặc định.

Điều này được đề cập trong chương 23.2.2.2.2. Tập hợp ICU của các tài liệu postres đề cập:

und-x-ICU (đối với “undefined”)
ICU “root” collation. Sử dụng điều này để có được một thứ tự sắp xếp ngôn ngữ hợp lý.

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.