Helpex - Trao đổi & giúp đỡ Đăng nhập
904

Giữa utf8_general_ciutf8_unicode_ci, có sự khác biệt nào về hiệu suất?

904 hữu ích 4 bình luận 344k xem chia sẻ
1407

Cả hai bộ sưu tập này đều dành cho mã hóa ký tự UTF-8. Sự khác biệt là cách văn bản được sắp xếp và so sánh.

Lưu ý: Vì MySQL 5.5.3, bạn nên sử dụng utf8mb4chứ không phải utf8. Cả hai đều đề cập đến mã hóa UTF-8, nhưng phiên bản cũ hơn utf8có giới hạn dành riêng cho MySQL, ngăn chặn việc sử dụng các ký tự được đánh số trên 0xFFFD.

  • Độ chính xác

    utf8mb4_unicode_ci được dựa trên tiêu chuẩn Unicode để sắp xếp và so sánh, sắp xếp chính xác trong một phạm vi ngôn ngữ rất rộng.

    utf8mb4_general_ci không thực hiện tất cả các quy tắc sắp xếp Unicode, điều này sẽ dẫn đến việc sắp xếp không mong muốn trong một số trường hợp, chẳng hạn như khi sử dụng các ngôn ngữ hoặc ký tự cụ thể.

  • Hiệu suất

    utf8mb4_general_ci nhanh hơn khi so sánh và sắp xếp, bởi vì nó cần một loạt các phím tắt liên quan đến hiệu suất.

    Trên các máy chủ hiện đại, hiệu suất tăng này sẽ là tất cả nhưng không đáng kể. Nó đã được nghĩ ra trong một thời gian khi các máy chủ có một phần rất nhỏ hiệu năng CPU của các máy tính ngày nay.

    utf8mb4_unicode_ci, sử dụng các quy tắc Unicode để sắp xếp và so sánh, sử dụng một thuật toán khá phức tạp để sắp xếp chính xác trong một loạt các ngôn ngữ và khi sử dụng một loạt các ký tự đặc biệt. Các quy tắc này cần phải tính đến các quy ước cụ thể về ngôn ngữ; không phải ai cũng sắp xếp các nhân vật của mình theo cái mà chúng ta gọi là "thứ tự chữ cái".

Theo như ngôn ngữ Latin (tức là "Châu Âu"), không có nhiều khác biệt giữa sắp xếp Unicode và utf8mb4_general_cisắp xếp đơn giản hóa trong MySQL, nhưng vẫn có một vài khác biệt:

  • Ví dụ: đối chiếu Unicode sắp xếp "ß" như "ss" và "" như "OE" như mọi người sử dụng các ký tự đó thường muốn, trong khi utf8mb4_general_cisắp xếp chúng thành các ký tự đơn (có lẽ giống như "s" và "e") .

  • Một số ký tự Unicode được định nghĩa là không thể biết được, điều đó có nghĩa là chúng không nên được tính theo thứ tự sắp xếp và thay vào đó sẽ chuyển sang ký tự tiếp theo. utf8mb4_unicode_cixử lý những điều này đúng.

Trong các ngôn ngữ không phải là tiếng Latin, chẳng hạn như ngôn ngữ châu Á hoặc ngôn ngữ có bảng chữ cái khác nhau, có thể có nhiều sự khác biệt hơn giữa sắp xếp Unicode và utf8mb4_general_cisắp xếp đơn giản hóa . Sự phù hợp của utf8mb4_general_ciý chí phụ thuộc rất nhiều vào ngôn ngữ được sử dụng. Đối với một số ngôn ngữ, nó sẽ khá bất cập.

Bạn nên dùng gì?

Gần như chắc chắn không có lý do để sử dụng utf8mb4_general_cinữa, vì chúng ta đã bỏ lại điểm mà tốc độ CPU đủ thấp để sự khác biệt hiệu năng sẽ là quan trọng. Cơ sở dữ liệu của bạn gần như chắc chắn sẽ bị giới hạn bởi các nút thắt khác hơn thế này.

Sự khác biệt về hiệu suất sẽ chỉ có thể đo lường được trong các tình huống cực kỳ chuyên biệt, và nếu đó là bạn, có lẽ bạn đã biết về nó. Nếu bạn gặp phải sự sắp xếp chậm, trong hầu hết các trường hợp, đó sẽ là một vấn đề với chỉ mục / kế hoạch truy vấn của bạn. Thay đổi chức năng đối chiếu của bạn không nên nằm trong danh sách những thứ cần khắc phục sự cố.

Trước đây, một số người khuyên nên sử dụng utf8mb4_general_citrừ khi việc sắp xếp chính xác sẽ đủ quan trọng để biện minh cho chi phí hiệu suất. Ngày nay, chi phí hiệu suất đó đã biến mất và các nhà phát triển đang đối xử với quốc tế hóa nghiêm túc hơn.

Một điều khác tôi sẽ nói thêm là ngay cả khi bạn biết ứng dụng của mình chỉ hỗ trợ ngôn ngữ tiếng Anh, thì vẫn có thể cần xử lý tên của mọi người, thường có thể chứa các ký tự được sử dụng trong các ngôn ngữ khác, trong đó việc sắp xếp chính xác cũng quan trọng. . Sử dụng các quy tắc Unicode cho mọi thứ giúp bạn yên tâm hơn rằng những người Unicode rất thông minh đã làm việc rất chăm chỉ để sắp xếp công việc đúng cách.

1407 hữu ích 5 bình luận chia sẻ
144

Tôi muốn biết sự khác biệt hiệu suất giữa việc sử dụng utf8_general_ciutf8_unicode_ci, nhưng tôi không tìm thấy bất kỳ điểm chuẩn nào được liệt kê trên internet, vì vậy tôi đã quyết định tự tạo điểm chuẩn.

Tôi đã tạo một bảng rất đơn giản với 500.000 hàng:

CREATE TABLE test(
  ID INT(11) DEFAULT NULL,
  Description VARCHAR(20) DEFAULT NULL
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;

Sau đó, tôi điền nó với dữ liệu ngẫu nhiên bằng cách chạy thủ tục được lưu trữ này:

CREATE PROCEDURE randomizer()
BEGIN
  DECLARE i INT DEFAULT 0;
  DECLARE random CHAR(20) ;
  theloop: loop
    SET random = CONV(FLOOR(RAND() * 99999999999999), 20, 36);
    INSERT INTO test VALUES (i+1, random);
    SET i=i+1;
    IF i = 500000 THEN
      LEAVE theloop;
    END IF;
  END LOOP theloop;
END

Sau đó, tôi đã tạo các thủ tục được lưu trữ sau đây để điểm chuẩn đơn giản SELECT, SELECTvới LIKEvà sắp xếp ( SELECTvới ORDER BY):

CREATE PROCEDURE benchmark_simple_select()
BEGIN
  DECLARE i INT DEFAULT 0;
  theloop: loop
    SELECT *
    FROM test
    WHERE Description = 'test' COLLATE utf8_general_ci;
    SET i = i + 1;
    IF i = 30 THEN
      LEAVE theloop;
    END IF;
  END LOOP theloop;
END;

CREATE PROCEDURE benchmark_select_like()
BEGIN
  DECLARE i INT DEFAULT 0;
  theloop: loop
    SELECT *
    FROM test
    WHERE Description LIKE '%test' COLLATE utf8_general_ci;
    SET i = i + 1;
    IF i = 30 THEN
      LEAVE theloop;
    END IF;
  END LOOP theloop;
END;

CREATE PROCEDURE benchmark_order_by()
BEGIN
  DECLARE i INT DEFAULT 0;
  theloop: loop
    SELECT *
    FROM test
    WHERE ID > FLOOR(1 + RAND() * (400000 - 1))
    ORDER BY Description COLLATE utf8_general_ci LIMIT 1000;
    SET i = i + 1;
    IF i = 10 THEN
      LEAVE theloop;
    END IF;
  END LOOP theloop;
END;

Trong các thủ tục lưu trữ trên utf8_general_ciđối chiếu được sử dụng, nhưng tất nhiên trong các thử nghiệm tôi đã sử dụng cả utf8_general_ciutf8_unicode_ci.

Tôi đã gọi mỗi thủ tục được lưu trữ 5 lần cho mỗi đối chiếu (5 lần cho utf8_general_civà 5 lần cho utf8_unicode_ci) và sau đó tính các giá trị trung bình.

Kết quả của tôi là:

benchmark_simple_select()

  • với utf8_general_ci: 9,957 ms
  • với utf8_unicode_ci: 10.271 ms

Trong tiêu chuẩn này sử dụng utf8_unicode_cilà chậm hơn utf8_general_ci3,2%.

benchmark_select_like()

  • với utf8_general_ci: 11,441 ms
  • với utf8_unicode_ci: 12.811 ms

Trong điểm chuẩn này sử dụng utf8_unicode_cilà chậm hơn utf8_general_ci12%.

benchmark_order_by()

  • với utf8_general_ci: 11.944 ms
  • với utf8_unicode_ci: 12.887 ms

Trong điểm chuẩn này sử dụng utf8_unicode_cichậm hơn utf8_general_ci7,9%.

144 hữu ích 3 bình luận chia sẻ
36

Bài đăng này mô tả nó rất độc đáo.

Tóm lại: utf8_unicode_ci sử dụng Thuật toán đối chiếu Unicode như được định nghĩa trong các tiêu chuẩn Unicode, trong khi utf8_general_ci là một thứ tự sắp xếp đơn giản hơn dẫn đến kết quả sắp xếp "kém chính xác".

36 hữu ích 5 bình luận chia sẻ
6

Xem hướng dẫn sử dụng mysql, phần Bộ ký tự Unicode :

Đối với bất kỳ bộ ký tự Unicode nào, các thao tác được thực hiện bằng cách đối chiếu _general_ci sẽ nhanh hơn các thao tác đối với đối chiếu _unicode_ci. Ví dụ, so sánh cho đối chiếu utf8_general_ci nhanh hơn, nhưng ít chính xác hơn so với so sánh cho utf8_unicode_ci. Lý do cho điều này là utf8_unicode_ci hỗ trợ ánh xạ như mở rộng; nghĩa là, khi một nhân vật so sánh bằng với sự kết hợp của các nhân vật khác. Ví dụ, trong tiếng Đức và một số ngôn ngữ khác, ß ß có nghĩa là bằng ss ss. utf8_unicode_ci cũng hỗ trợ các cơn co thắt và các ký tự không thể biết được. utf8_general_ci là một đối chiếu kế thừa không hỗ trợ các bản mở rộng, các cơn co thắt hoặc các ký tự không thể biết được. Nó chỉ có thể so sánh một-một giữa các nhân vật.

Vì vậy, để tóm tắt, utf_general_ci sử dụng một bộ so sánh nhỏ hơn và ít chính xác hơn (theo tiêu chuẩn) so với utf_unicode_ci sẽ thực hiện toàn bộ tiêu chuẩn. Bộ general_ci sẽ nhanh hơn vì có ít tính toán hơn.

6 hữu ích 5 bình luận chia sẻ
6

Nói ngắn gọn:

Nếu bạn cần thứ tự sắp xếp tốt hơn - sử dụng utf8_unicode_ci(đây là phương pháp ưa thích),

nhưng nếu bạn hoàn toàn quan tâm đến hiệu suất - sử dụng utf8_general_ci, nhưng biết rằng nó hơi lỗi thời.

Sự khác biệt về hiệu suất là rất nhẹ.

6 hữu ích 0 bình luận chia sẻ
2

Một số chi tiết (PL)

Như chúng ta có thể đọc ở đây ( Peter Gulutzan ) có sự khác biệt trong việc sắp xếp / so sánh chữ đánh bóng "" (L với đột quỵ - html esc Ł:) (chữ thường: "ł" - html esc ł:) - chúng ta có giả định sau:

utf8_polish_ci      Ł greater than L and less than M
utf8_unicode_ci     Ł greater than L and less than M
utf8_unicode_520_ci Ł equal to L
utf8_general_ci     Ł greater than Z

Trong thư ngôn ngữ đánh bóng Łlà sau thư Lvà trước M. Không ai trong số mã hóa này tốt hơn hay xấu hơn - nó phụ thuộc vào nhu cầu của bạn.

2 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ mysql unicode , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading