В чем разница между utf8_general_ci и utf8_unicode_ci - PullRequest
941 голосов
/ 20 апреля 2009

Между utf8_general_ci и utf8_unicode_ci, есть ли различия с точки зрения производительности?

Ответы [ 6 ]

1437 голосов
/ 20 апреля 2009

Эти два сопоставления предназначены для кодировки символов UTF-8. Различия в том, как текст сортируется и сравнивается.

Примечание. Начиная с MySQL 5.5.3, вы должны использовать utf8mb4 вместо utf8. Оба они ссылаются на кодировку UTF-8, но более старый utf8 имел специфичное для MySQL ограничение, запрещающее использование символов с номерами выше 0xFFFD.

  • Точность

    utf8mb4_unicode_ci основан на стандарте Unicode для сортировки и сравнения, который точно сортирует на самых разных языках.

    utf8mb4_general_ci не в состоянии реализовать все правила сортировки Unicode, что приведет к нежелательной сортировке в некоторых ситуациях, например при использовании определенных языков или символов.

  • Производительность

    utf8mb4_general_ci быстрее при сравнении и сортировке, потому что для этого требуется множество ярлыков, связанных с производительностью.

    На современных серверах это повышение производительности будет практически незначительным. Он был разработан в то время, когда серверы имели небольшую долю производительности ЦП современных компьютеров.

    utf8mb4_unicode_ci, который использует правила Unicode для сортировки и сравнения, использует довольно сложный алгоритм для правильной сортировки в широком диапазоне языков и при использовании широкого диапазона специальных символов. Эти правила должны учитывать языковые соглашения; не каждый сортирует своих персонажей в том, что мы назвали бы «алфавитным порядком».

Что касается латиницы (то есть "европейских") языков, между сортировкой Unicode и упрощенной utf8mb4_general_ci сортировкой в ​​MySQL нет большой разницы, но есть еще несколько отличий:

  • Например, параметры сортировки Unicode сортируют "ß", например, "ss", и "" ", например," OE ", как обычно хотят люди, использующие эти символы, тогда как utf8mb4_general_ci сортирует их как отдельные символы (предположительно, как "s" и "e" соответственно).

  • Некоторые символы Юникода определены как игнорируемые, что означает, что они не должны учитываться в порядке сортировки, а сравнение должно перейти к следующему символу. utf8mb4_unicode_ci обрабатывает их правильно.

В нелатинских языках, таких как азиатские языки или языки с разными алфавитами, может быть много больше различий между сортировкой Unicode и упрощенной сортировкой utf8mb4_general_ci. Пригодность utf8mb4_general_ci будет сильно зависеть от используемого языка. Для некоторых языков это будет совершенно неадекватно.

Что вы должны использовать?

Почти наверняка нет смысла использовать utf8mb4_general_ci, поскольку мы оставили точку, когда скорость процессора достаточно низкая, чтобы разница в производительности была важной. Ваша база данных почти наверняка будет ограничена другими узкими местами, кроме этой.

Разница в производительности будет ощутима только в крайне специализированных ситуациях, и если это вы, вы, вероятно, уже знаете об этом. Если вы испытываете медленную сортировку, почти во всех случаях это будет проблемой с вашими индексами / планом запросов. Изменение функции сортировки не должно занимать одно из первых мест для устранения неполадок.

В прошлом некоторые люди рекомендовали использовать utf8mb4_general_ci, за исключением случаев, когда точная сортировка должна была стать достаточно важной, чтобы оправдать снижение производительности. Сегодня эта производительность почти исчезла, и разработчики относятся к интернационализации более серьезно.

Еще одна вещь, которую я добавлю, заключается в том, что даже если вы знаете, что ваше приложение поддерживает только английский язык, оно все равно может иметь дело с именами людей, которые часто могут содержать символы, используемые в других языках, для которых оно так же важно правильно сортировать. Использование правил Unicode для всего помогает добавить душевного спокойствия, что очень умные люди Unicode очень усердно работали, чтобы заставить сортировку работать правильно.

146 голосов
/ 02 марта 2013

Я хотел знать, в чем разница в производительности между использованием utf8_general_ci и utf8_unicode_ci, но я не нашел никаких тестов в Интернете, поэтому решил сам создать тесты.

Я создал очень простую таблицу с 500 000 строк:

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

Затем я заполнил его случайными данными, запустив эту хранимую процедуру:

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

Затем я создал следующие хранимые процедуры для сравнения простых SELECT, SELECT с LIKE и сортировки (SELECT с 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;

В хранимых процедурах выше utf8_general_ci используется сортировка, но, конечно же, во время тестов я использовал и utf8_general_ci и utf8_unicode_ci.

Я вызывал каждую хранимую процедуру 5 раз для каждого сопоставления (5 раз для utf8_general_ci и 5 раз для utf8_unicode_ci) и затем рассчитывал средние значения.

Мои результаты:

benchmark_simple_select()

  • с utf8_general_ci: 9,957 мс
  • с utf8_unicode_ci: 10,271 мс

В этом тесте использование utf8_unicode_ci медленнее, чем utf8_general_ci на 3,2%.

benchmark_select_like()

  • с utf8_general_ci: 11,441 мс
  • с utf8_unicode_ci: 12,811 мс

В этом тесте использование utf8_unicode_ci медленнее, чем utf8_general_ci на 12%.

benchmark_order_by()

  • с utf8_general_ci: 11,944 мс
  • с utf8_unicode_ci: 12,887 мс

В этом тесте использование utf8_unicode_ci медленнее, чем utf8_general_ci на 7,9%.

36 голосов
/ 01 января 2010

Этот пост описывает это очень хорошо.

Вкратце: utf8_unicode_ci использует алгоритм сортировки Unicode, как определено в стандартах Unicode, тогда как utf8_general_ci - более простой порядок сортировки, который приводит к "менее точным" результатам сортировки.

6 голосов
/ 20 апреля 2009

См. Руководство по mysql, Наборы символов Unicode раздел:

Для любого набора символов Юникода, операции, выполненные с использованием Параметры сортировки _general_ci выполняются быстрее, чем параметры сортировки _unicode_ci. Например, сравнения для Сортировка utf8_general_ci быстрее, но чуть менее правильно, чем сравнения для utf8_unicode_ci. Причиной этого является то, что utf8_unicode_ci поддерживает такие отображения как расширения; то есть когда один персонаж сравнивается как равный комбинации других персонажей. За Например, на немецком и некоторых других языки «ß» равно «ss». utf8_unicode_ci также поддерживает схватки и игнорируемые персонажи. utf8_general_ci - устаревшее сопоставление который не поддерживает расширения, сокращения или игнорируемые персонажи. Это может сделать только один к одному сравнения между символами.

Таким образом, чтобы подвести итог, utf_general_ci использует меньший и менее правильный (согласно стандарту) набор сравнений, чем utf_unicode_ci, который должен реализовать весь стандарт. Набор general_ci будет быстрее, потому что требуется меньше вычислений.

5 голосов
/ 06 марта 2017

Кратко:

Если вам нужен лучший порядок сортировки - используйте utf8_unicode_ci (это предпочтительный метод), * ​​1006 *

но если вы крайне заинтересованы в производительности - используйте utf8_general_ci, но знайте, что она немного устарела.

Различия в производительности очень незначительны.

2 голосов
/ 20 ноября 2018

Некоторые детали (PL)

Как мы можем прочитать здесь ( Питер Гулутзан ) есть разница в сортировке / сравнении польской буквы "Ł" (L с ударом - html esc: Ł) (ниже case: "ł" - html esc: ł) - у нас есть следующее предположение:

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

На польском языке буква Ł стоит после буквы L и перед M. Ни одна из этих кодировок не является лучше или хуже - это зависит от ваших потребностей.

...