Между utf8_general_ci
и utf8_unicode_ci
есть ли различия с точки зрения производительности?
utf8[mb4]_unicode_ci
, вам может понравиться utf8[mb4]_unicode_520_ci
еще больше.
utf8mb4_0900_ai_ci
.
Между utf8_general_ci
и utf8_unicode_ci
есть ли различия с точки зрения производительности?
utf8[mb4]_unicode_ci
, вам может понравиться utf8[mb4]_unicode_520_ci
еще больше.
utf8mb4_0900_ai_ci
.
Ответы:
Эти два сопоставления предназначены для кодировки символов UTF-8. Различия в том, как текст сортируется и сравнивается.
Примечание: в MySQL вы должны использовать, utf8mb4
а не utf8
. Это сбивает с толку utf8
ошибочную реализацию UTF-8 из ранних версий MySQL, которая остается только для обратной совместимости. Фиксированной версии дали имя utf8mb4
.
Примечание. В новых версиях MySQL обновлены правила сортировки Unicode, доступные под именами, например, utf8mb4_0900_ai_ci
для эквивалентных правил, основанных на Unicode 9.0, и без эквивалентного _general
варианта. Люди, читающие это сейчас, вероятно, должны использовать одно из этих новых сопоставлений вместо либо, _unicode
либо _general
. Многое из того, что написано ниже, больше не представляет большого интереса, если вместо этого вы можете использовать один из более новых сопоставлений.
Ключевые отличия
utf8mb4_unicode_ci
основан на официальных правилах Unicode для универсальной сортировки и сравнения, которая точно сортирует по широкому спектру языков.
utf8mb4_general_ci
Это упрощенный набор правил сортировки, цель которого - сделать все возможное, используя множество ярлыков, предназначенных для повышения скорости. Он не следует правилам Юникода и приведет к нежелательной сортировке или сравнению в некоторых ситуациях, например при использовании определенных языков или символов.
На современных серверах это повышение производительности будет практически незначительным. Он был разработан в то время, когда серверы имели небольшую долю производительности ЦП современных компьютеров.
Преимущества utf8mb4_unicode_ci
более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
за исключением случаев, когда точная сортировка будет достаточно важной, чтобы оправдать затраты производительности. Сегодня эта производительность практически исчезла, и разработчики относятся к интернационализации более серьезно.
Можно привести аргумент, что если скорость важнее для вас, чем точность, вы также можете вообще ничего не делать. Тривиально сделать алгоритм быстрее, если вам не нужно, чтобы он был точным. Таким образом, utf8mb4_general_ci
это компромисс, который, вероятно, не нужен по соображениям скорости и, вероятно, также не подходит по соображениям точности.
Еще одну вещь, которую я добавлю, это то, что даже если вы знаете, что ваше приложение поддерживает только английский язык, ему все равно может потребоваться работать с именами людей, которые часто могут содержать символы, используемые в других языках, для которых столь же важно правильно сортировать , Использование правил Unicode для всего помогает добавить душевного спокойствия, что очень умные люди Unicode очень усердно работали, чтобы заставить сортировку работать должным образом.
Что означают части
Во-первых, ci
для сортировки и сравнения без учета регистра . Это означает, что он подходит для текстовых данных, и случай не важен. Другие типы сопоставления cs
(чувствительны к регистру) для текстовых данных, где регистр важен, и bin
для того, где кодирование должно соответствовать, бит за битом, что подходит для полей, которые действительно кодируются двоичными данными (включая, например, Base64). Сортировка с учетом регистра приводит к некоторым странным результатам, а сравнение с учетом регистра может привести к тому, что повторяющиеся значения, отличающиеся только регистром букв, поэтому регистры с учетом регистра теряют предпочтение для текстовых данных - если регистр важен для вас, то в противном случае игнорируемая пунктуация и так далее, вероятно, также важно, и двоичное сопоставление может быть более подходящим.
Далее unicode
или general
ссылается на конкретные правила сортировки и сравнения - в частности, способ нормализации или сравнения текста. Есть много различных наборов правил для кодирования символов utf8mb4, с unicode
и general
быть два , которые пытаются хорошо работать во всех возможных языках , а не один конкретный один. Различия между этими двумя наборами правил являются предметом этого ответа. Обратите внимание, что unicode
используются правила из Unicode 4.0. Последние версии MySQL добавляют наборы правил, unicode_520
используя правила из Unicode 5.2, и 0900
(отбрасывая часть "unicode_"), используя правила из Unicode 9.0.
И, наконец, utf8mb4
конечно же, внутренняя кодировка символов. В этом ответе я говорю только о Unicode-кодировках.
utf8_general_ci
: это просто не работает. Это возвращение к плохим старым временам ASCII-ступенек с пятидесятилетней давности. Сопоставление без учета регистра в Юникоде невозможно без карты сгиба из UCD. Например, «Σίσυφος» содержит три разных сигмы; или как строчная буква «TSCHüẞ» - «tschüβ», а прописная буква «tschüβ» - «TSCHÜSS». Вы можете быть правы, или вы можете быть быстрым. Поэтому вы должны использовать utf8_unicode_ci
, потому что, если вы не заботитесь о правильности, то тривиально сделать это бесконечно быстро.
"か" == "が"
или "ǽ" == "æ"
. Для сортировки это имеет смысл, но может быть удивительно, когда вы выбираете с помощью равенств или имеете дело с уникальными индексами - bugs.mysql.com/bug.php?id=16526
utf8mb4
- единственный правильный выбор . С utf8
вы застряли в каком - то MySQL-только, 3-байтовый вариант UTF8 , что только MySQL (и MariaDB) знают , что делать с. Остальной мир использует UTF8, который может содержать до 4 байтов на символ . Разработчики MySQL неправильно назвали свою кодировку homebrew utf8
и, чтобы не нарушать обратную совместимость, теперь они должны ссылаться на настоящий UTF8 как utf8mb4
.
Я хотел знать, в чем разница в производительности между использованием 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%.
utf8_general_ci
слишком минимален, чтобы его стоило использовать.
CONV(FLOOR(RAND() * 99999999999999), 20, 36)
генерирует только ASCII, и никаких символов Unicode для обработки алгоритмами сопоставления. 2) Description = 'test' COLLATE ...
и Description LIKE 'test%' COLLATE ...
обрабатывают только одну строку («тест») во время выполнения, не так ли? 3) В реальных приложениях столбцы, используемые при упорядочении, вероятно, будут проиндексированы, и скорость индексации для разных сопоставлений с реальным текстом, не относящимся к ASCII, может отличаться.
Этот пост описывает это очень хорошо.
Вкратце: utf8_unicode_ci использует алгоритм сопоставления Unicode, как определено в стандартах Unicode, тогда как utf8_general_ci - более простой порядок сортировки, который приводит к «менее точным» результатам сортировки.
utf8_unicode_ci
и сделайте вид, что другого не существует.
utf8_general_ci
может быть для вас
См. Руководство по mysql, раздел « Наборы символов Unicode »:
Для любого набора символов 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
и сделайте вид, что неисправной версии не существует.
0
а 1
не бул. :) Например, выбор географических точек в ограничительной рамке - это аппроксимация «соседних точек», которая не так хороша, как вычисление расстояния между точкой и контрольной точкой и фильтрация по ней. Но оба они являются приблизительными, и на самом деле, полная корректность в большинстве случаев недостижима. См. Парадокс береговой линии и IEEE 754
1/3
Вкратце:
Если вам нужен лучший порядок сортировки - используйте utf8_unicode_ci
(это предпочтительный метод),
но если вы крайне заинтересованы в производительности - используйте utf8_general_ci
, но знайте, что она немного устарела.
Различия с точки зрения производительности очень незначительны.
Как мы можем прочитать здесь ( Питер Гулутзан ), есть разница в сортировке / сравнении польской буквы "Ł" (L с штрихом - html esc:) Ł
(нижний регистр: "ł" - 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
. Ни одна из этих кодировок не является лучше или хуже - это зависит от ваших потребностей.
Есть две большие разницы: сортировка и сопоставление символов:
Сортировка :
utf8mb4_general_ci
удаляет все акценты и сортирует их по одному, что может привести к неверным результатам сортировки.utf8mb4_unicode_ci
сортирует точно.Подбор персонажей
Они соответствуют персонажам по-разному.
Например, у utf8mb4_unicode_ci
вас есть i != ı
, но в utf8mb4_general_ci
нем держит ı=i
.
Например, представьте, что у вас есть ряд с name="Yılmaz"
. затем
select id from users where name='Yilmaz';
возвратил бы строку, если есть словосочетание utf8mb4_general_ci
, но если оно будет размещено вместе с utf8mb4_unicode_ci
ним, не вернет строку!
С другой стороны , мы имеем , что a=ª
и ß=ss
в utf8mb4_unicode_ci
которых не бывает в utf8mb4_general_ci
. Итак , представьте , у вас есть строка с name="ªßi"
, то
select id from users where name='assi';
вернет строку, если используется словосочетание utf8mb4_unicode_ci
, но не вернет строку, если для словосочетания установлено значение utf8mb4_general_ci
.
Полный список совпадений для каждого словосочетания можно найти здесь .
Согласно этому сообщению, MySQL 5.7 значительно повышает производительность при использовании utf8mb4_general_ci вместо utf8mb4_unicode_ci: https://www.percona.com/blog/2019/02/27/charset-and-collation-settings-impact. -он-MySQL-производительность /