В чем разница между utf8 general ci и utf8 unicode ci

между utf8_general_ci и utf8_unicode_ci, есть ли разница в плане производительности?

5 ответов


эти две сортировки предназначены для кодировки символов 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, но есть еще несколько различий:

  • например, параметры сортировки Юникода сортируют " ß "как" 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 очень много работали, чтобы сортировка работала правильно.


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

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

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

затем я создал следующие хранимые процедуры для проверки простого выбора, выбора с помощью LIKE и сортировка (выбрать по порядку):

CREATE 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: 9957 МС
benchmark_simple_select () с utf8_unicode_ci: 10271 ms
В этом тесте использовать utf8_unicode_ci медленнее, чем utf8_general_ci на 3,2%.

benchmark_select_like () с utf8_general_ci: 11441 ms
benchmark_select_like () с utf8_unicode_ci: 12811 ms
В этом тесте использование utf8_unicode_ci медленнее, чем utf8_general_ci на 12%.

benchmark_order_by () с utf8_general_ci: 11944 ms
benchmark_order_by() с utf8_unicode_ci: 12887 ms
В этом тесте использовать utf8_unicode_ci медленнее, чем utf8_general_ci на 7,9%.


этот пост описывает это очень красиво.

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


см. руководство 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 будет быстрее, потому что меньше вычислений.


вкратце:

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

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

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