PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Các hợp tác mạnh mẽ hơn với hỗ trợ ICU trong PostgreSQL 10

Trong bài viết này, tôi muốn giới thiệu hỗ trợ ICU trong PostgreSQL, mà tôi đã làm việc cho PostgreSQL phiên bản 10, sẽ xuất hiện vào cuối năm nay.

Sắp xếp

Sắp xếp là một chức năng quan trọng của hệ thống cơ sở dữ liệu. Đầu tiên, người dùng thường muốn xem dữ liệu được sắp xếp. Bất kỳ kết quả truy vấn nào chứa nhiều hơn một hàng và dành cho người dùng cuối có thể sẽ muốn được sắp xếp, chỉ để có trải nghiệm người dùng tốt hơn. Thứ hai, rất nhiều chức năng bên trong của hệ thống cơ sở dữ liệu phụ thuộc vào việc sắp xếp dữ liệu hoặc có sẵn dữ liệu được sắp xếp. Các chỉ mục B-tree là một ví dụ rõ ràng. Chỉ số BRIN có kiến ​​thức về trật tự. Phân vùng phạm vi phải so sánh các giá trị. Hợp nhất các phép nối phụ thuộc vào dữ liệu đầu vào được sắp xếp. Ý tưởng phổ biến đối với các kỹ thuật khác nhau này là, nói một cách đại khái, nếu bạn đã sắp xếp dữ liệu và bạn biết mình đang tìm gì, thì việc xác định vị trí nơi cần tìm sẽ nhanh hơn nhiều.

Có hai khía cạnh quan trọng để phân loại. Một là thuật toán sắp xếp. Đây là một chủ đề tiêu chuẩn trong khoa học máy tính và rất nhiều công việc đã được thực hiện trong PostgreSQL trong những năm qua để tinh chỉnh các thuật toán và phương pháp sắp xếp khác nhau, nhưng đó không phải là điều tôi sẽ viết về. Cái khác là quyết định mọi thứ nên theo thứ tự nào, cái mà chúng ta gọi là đối chiếu. Trong nhiều trường hợp, sự lựa chọn đó là hiển nhiên. 1 đến trước 2. FALSE đến trước TRUE… à, ai đó đã tự ý quyết định điều đó. A thường đứng trước B. Nhưng khi nói đến văn bản ngôn ngữ tự nhiên, mọi thứ trở nên thú vị. Có nhiều cách khác nhau để sắp xếp văn bản và các phương pháp thực tế để đối chiếu các chuỗi văn bản phức tạp hơn mức có thể thấy rõ. Các ngôn ngữ khác nhau thích các thứ tự sắp xếp khác nhau, nhưng ngay cả trong một ngôn ngữ, có thể có các biến thể cho các ứng dụng khác nhau. Và có những chi tiết cần lo lắng, chẳng hạn như phải làm gì về khoảng trắng, dấu câu, sự khác biệt về chữ hoa và chữ thường, dấu phụ, v.v. Tra cứu Thuật toán đối chiếu Unicode để hiểu rõ hơn về điều này.

Trước khi tính năng ICU được cam kết, tất cả chức năng này đều được thư viện C hỗ trợ trong hệ điều hành. Về cơ bản, PostgreSQL chỉ chuyển các chuỗi tới strcmp() , strcoll() , và những thứ tương tự và làm việc với kết quả. Các thư viện C trong các hệ điều hành khác nhau triển khai các biến thể và sắc thái đối chiếu khác nhau được đề cập ở trên cho các mức chức năng và chất lượng khác nhau, vì vậy PostgreSQL có thể thực hiện những gì hệ điều hành của bạn có thể làm.

Thay đổi ảnh ghép

Sự cố bắt đầu xảy ra nếu hệ điều hành cần thay đổi đối chiếu mà nó cung cấp. Vì sao họ muốn làm việc đó? Nó có thể là đối chiếu trước đó đã bị sai và phải được sửa chữa. Có thể một tiêu chuẩn mới cho một ngôn ngữ đã được xuất bản và đối chiếu sẽ được cập nhật cho điều đó. Có thể biểu diễn bên trong của dữ liệu đối chiếu và chuỗi đã bị thay đổi vì lý do hiệu suất hoặc vì cần phải triển khai chức năng bổ sung. Đối với nhiều chương trình, đây không phải là một vấn đề. Bạn có thể chỉ thấy một đầu ra có thứ tự hơi khác một chút, nếu bạn nhận thấy sự khác biệt. Tuy nhiên, đối với một hệ thống cơ sở dữ liệu, đây là một vấn đề lớn. Như đã mô tả ở trên, PostgreSQL lưu trữ dữ liệu được sắp xếp trong các chỉ mục và những nơi khác và dựa vào thứ tự sắp xếp để chính xác. Nếu thứ tự sắp xếp không chính xác, tra cứu chỉ mục có thể không tìm thấy dữ liệu thực sự ở đó. Hoặc ghi vào một chỉ mục sẽ ghi vào một nơi khác. Hoặc dữ liệu được ghi vào hoặc đọc từ phân vùng sai. Điều này có thể dẫn đến dữ liệu trùng lặp sai hoặc xuất hiện mất dữ liệu vì dữ liệu không được tìm kiếm ở đâu. Nói cách khác, nó có thể dẫn đến hỏng dữ liệu và mất dữ liệu (rõ ràng).

Thật không may, chúng tôi không thể làm được gì nhiều cho đến nay. Hệ điều hành cập nhật các đối chiếu của chúng bất cứ khi nào chúng cảm thấy thích, có lẽ là một phần của quá trình nâng cấp lên gói thư viện C của chúng. Không có cách nào để tìm ra điều này một cách hợp lý, hoặc có lẽ bằng cách kiểm tra chi tiết các gói cập nhật. Và thậm chí sau đó, bạn sẽ từ chối một bản cập nhật quan trọng của thư viện C của mình vì bạn nhận thấy rằng đối chiếu trong một số ngôn ngữ bạn không sử dụng đã bị thay đổi? Đó là một tình huống rất khó chịu.

Nhập ICU

Vậy ICU đi vào đâu? ICU, International Components for Unicode, là một thư viện cung cấp các phương tiện quốc tế hóa và bản địa hóa, bao gồm cả đối chiếu. Vì vậy, về mặt đó, nó là một giải pháp thay thế cho việc sử dụng các cơ sở trong thư viện C tiêu chuẩn. Điều tốt đẹp là ICU cung cấp rõ ràng một số đảm bảo về tính ổn định của các ảnh ghép:

  • Bản đối chiếu sẽ không bị thay đổi theo cách không tương thích như một phần của bản cập nhật phát hành nhỏ.
  • Đối chiếu có một phiên bản, có thể được kiểm tra và khi đối chiếu thay đổi theo cách không tương thích, phiên bản sẽ thay đổi.

Đối với người dùng PostgreSQL, điều này có nghĩa trong thực tế:

  • Cập nhật gói hệ điều hành định kỳ sẽ không ảnh hưởng đến tính hợp lệ của dữ liệu được sắp xếp. Kể từ một postgres nhị phân được liên kết với một phiên bản chính cụ thể của libicu , việc nâng cấp gói hệ điều hành thông thường sẽ không kết thúc với postgres được liên kết với phiên bản chính mới của libicu , miễn là a) bạn không cập nhật các gói PostgreSQL hoặc b) các gói PostgreSQL vẫn được liên kết với cùng một phiên bản ICU chính như trước đây. Người đóng gói sẽ cần phải cẩn thận để duy trì điều này đúng cách, nhưng điều đó sẽ không quá khó khăn trong thực tế.
  • Khi các gói nâng cấp lớn và hệ điều hành thay đổi phiên bản đối chiếu, chúng tôi có một cách để phát hiện điều đó và cảnh báo người dùng. Hiện tại, chúng tôi chỉ cảnh báo và đưa ra một số nguyên tắc và công cụ để khắc phục mọi thứ, nhưng trong tương lai, chúng tôi có thể sẽ cải tiến và tự động hóa việc này hơn nữa.

(Để làm cho điều này rõ ràng hơn cho người đóng gói:Trong một nhánh ổn định của hệ điều hành của bạn, bạn không nên thay đổi phiên bản ICU chính mà một bộ gói PostgreSQL nhất định được liên kết với.)

Sử dụng ICU

Để có thể sử dụng điều này, PostgreSQL cần được xây dựng rõ ràng với sự hỗ trợ của ICU. Khi xây dựng từ nguồn, hãy sử dụng ./configure --with-icu cùng với các tùy chọn mong muốn khác. Chúng tôi mong đợi hầu hết các gói nhị phân lớn cũng cung cấp điều này theo mặc định. Khi điều này được thực hiện, các đối chiếu dựa trên ICU được cung cấp cùng với các đối chiếu dựa trên libc mà các bản phát hành trước đó cung cấp. (Vì vậy, việc xây dựng với hỗ trợ ICU không loại bỏ hỗ trợ đối chiếu libc; cả hai tồn tại cùng nhau.) Kiểm tra tài liệu để biết chi tiết về cách chọn đối chiếu dựa trên ICU so với đối chiếu dựa trên libc. Ví dụ:nếu trước đó bạn đã chỉ định

CREATE TABLE ... (... x text COLLATE "en_US" ...)

bây giờ bạn có thể làm

CREATE TABLE ... (... x text COLLATE "en-x-icu" ...)

Điều này sẽ cung cấp cho bạn hành vi người dùng có thể nhìn thấy gần giống như trước đây, ngoại trừ việc cơ sở dữ liệu của bạn sẽ dễ kiểm chứng hơn trong tương lai khi nâng cấp. (Trên Linux / glibc, thứ tự sắp xếp hầu như giống nhau, nhưng có thể có sự khác biệt nhỏ ở một số chi tiết. Tuy nhiên, nếu bạn đang sử dụng hệ điều hành có thư viện C hoàn toàn không hỗ trợ đối chiếu Unicode, chẳng hạn như macOS hoặc phiên bản cũ hơn của FreeBSD, thì đây sẽ là một thay đổi lớn - tốt hơn.)

Hiện tại, hỗ trợ ICU chỉ có sẵn cho các đối chiếu được chỉ định rõ ràng. Đối chiếu mặc định trong cơ sở dữ liệu vẫn luôn được cung cấp bởi thư viện C. Giải quyết đây là một dự án trong tương lai.

Nếu bạn nâng cấp cơ sở dữ liệu như vậy bằng pg_upgrade ví dụ như cài đặt PostgreSQL mới được liên kết với phiên bản ICU chính mới hơn đã thay đổi phiên bản đối chiếu của đối chiếu mà bạn đang sử dụng, khi đó bạn sẽ nhận được cảnh báo và sẽ phải sửa chữa, ví dụ:bất kỳ chỉ mục nào phụ thuộc vào đối chiếu. Hướng dẫn cho việc này cũng có trong tài liệu.

Các khóa viết tắt

Vì vậy, thay đổi này sẽ cung cấp một số cải tiến rất quan trọng cho sự bền vững lâu dài của hệ thống cơ sở dữ liệu. Nhưng ICU cũng là một cải tiến so với thư viện hệ thống C trong các lĩnh vực khác.

Ví dụ:PostgreSQL B-tree có thể lưu trữ những gì được gọi là khóa viết tắt để cải thiện hiệu suất và lưu trữ. Đối với các kiểu dữ liệu chuỗi văn bản, với thư viện C chuẩn, chúng tôi sẽ tính toán các khóa viết tắt này bằng cách sử dụng strxfrm() hàm số. Tuy nhiên, chúng tôi đã biết rằng nhiều thư viện C có nhiều lỗi và cách xử lý sai khiến cách tiếp cận này không đáng tin cậy. Vì vậy, việc tối ưu hóa các phím viết tắt hiện đang bị vô hiệu hóa đối với các kiểu dữ liệu chuỗi. Với ICU, chúng tôi có thể sử dụng các lệnh gọi API tương đương và tính toán các khóa viết tắt theo cách mà chúng tôi tin là đáng tin cậy và ổn định. Vì vậy, có thể có những cải thiện hiệu suất từ ​​động thái này.

Các ảnh ghép khác

Ngoài những cải tiến nội bộ về độ mạnh mẽ và hiệu suất, còn có một số chức năng hướng tới người dùng mới.

Đối với một số ngôn ngữ, nhiều hơn một thứ tự sắp xếp có thể phù hợp trong thực tế. (Điều này có thể giúp bạn bắt đầu.) Một ví dụ là đối với tiếng Đức, có một thứ tự sắp xếp tiêu chuẩn được sử dụng cho hầu hết các mục đích và thứ tự sắp xếp “danh bạ điện thoại” được sử dụng cho danh sách tên. Thư viện C tiêu chuẩn chỉ cung cấp một trong những biến thể đó (có thể là biến thể đầu tiên). Nhưng nếu bạn muốn viết một ứng dụng sắp xếp đúng, chẳng hạn như cả tên sản phẩm và tên khách hàng, bạn cần có khả năng sử dụng cả hai.

Ví dụ:ví dụ từ Wikipedia tiếng Đức hiện có thể được sao chép lại bằng PostgreSQL:

CREATE TABLE names (name text);

INSERT INTO names
    VALUES ('Göbel'), ('Goethe'), ('Goldmann'), ('Göthe'), ('Götz');

=> SELECT name FROM names ORDER BY name COLLATE "de-u-co-standard-x-icu";
   name
----------
 Göbel
 Goethe
 Goldmann
 Göthe
 Götz

=> SELECT name FROM names ORDER BY name COLLATE "de-u-co-phonebk-x-icu";
   name
----------
 Göbel
 Goethe
 Göthe
 Götz
 Goldmann

=> SELECT name FROM names ORDER BY name COLLATE "de-AT-u-co-phonebk-x-icu";
   name
----------
 Goethe
 Goldmann
 Göbel
 Göthe
 Götz

(Với glibc, COLLATE "de_DE"COLLATE "de_AT" thực sự trả lại đơn đặt hàng đầu tiên.)

Một cách thú vị để kết hợp một số tính năng có thể là sử dụng miền để tạo mô hình cho sự khác biệt được đề cập ở trên giữa tên sản phẩm và tên khách hàng:

CREATE DOMAIN product_name AS text COLLATE "de-u-co-standard-x-icu";
CREATE DOMAIN person_name AS text COLLATE "de-u-co-phonebk-x-icu";

(Đây chỉ là một ví dụ. Tất nhiên bạn cũng có thể đính kèm COLLATE đó các mệnh đề đến định nghĩa cột trực tiếp hoặc sử dụng chúng trong các truy vấn.)

Thậm chí nhiều ảnh ghép

Cuối cùng, và đây rõ ràng là điều mà thế giới đã chờ đợi, giờ đây đã có một cách để sắp xếp các biểu tượng cảm xúc một cách chính xác. Điều này là cần thiết để đảm bảo rằng tất cả các khuôn mặt mèo của bạn đều theo thứ tự thích hợp. So sánh

=# SELECT chr(x) FROM generate_series(x'1F634'::int, x'1F644'::int) AS _(x)
       ORDER BY chr(x) COLLATE "und-x-icu";
 chr
-----
 😴
 😵
 😶
 😷
 😸
 😹
 😺
 😻
 😼
 😽
 😾
 😿
 🙀
 🙁
 🙂
 🙃
 🙄

với

=# CREATE COLLATION "und-u-co-emoji-x-icu" (provider = icu, locale = 'und-u-co-emoji');
=# SELECT chr(x) FROM generate_series(x'1F634'::int, x'1F644'::int) AS _(x)
       ORDER BY chr(x) COLLATE "und-u-co-emoji-x-icu";
 chr
-----
 🙂
 🙃
 😶
 🙄
 😴
 😷
 😵
 🙁
 😺
 😸
 😹
 😻
 😼
 😽
 🙀
 😿
 😾

Vâng, thực sự có một tiêu chuẩn về điều này.

Sẽ có nhiều hơn nữa

Điều này chỉ là khởi đầu. ICU cung cấp rất nhiều chức năng trong lĩnh vực này mà chúng tôi chưa giới thiệu qua PostgreSQL. Có các tùy chọn để phân loại không phân biệt chữ hoa chữ thường, phân loại không phân biệt trọng âm và hoàn toàn tùy chỉnh đối chiếu. Tìm kiếm những thứ đó trong các bản phát hành PostgreSQL trong tương lai.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách truy vấn mảng jsonb bằng toán tử IN

  2. Tạo cơ sở dữ liệu Postgres bằng python

  3. INSERT [...] ON CONFLICT có thể được sử dụng cho các vi phạm khóa ngoại không?

  4. Lỗi postgres khi cập nhật dữ liệu cột

  5. Tổng quan về các phương thức JOIN trong PostgreSQL