В чем разница между 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
, но знайте, что это немного устарело.
различия с точки зрения производительности очень незначительны.