Вопрос

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

Это было полезно?

Решение

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

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

Ключевые отличия

  • utf8mb4_unicode_ci основан на официальных правилах Unicode для универсальной сортировки и сравнения, которые обеспечивают точную сортировку на широком спектре языков.

  • utf8mb4_general_ci это упрощенный набор правил сортировки, цель которого - работать как можно лучше, используя при этом множество коротких путей, направленных на повышение скорости.Это не соответствует правилам Unicode и приведет к нежелательной сортировке или сравнению в некоторых ситуациях, например, при использовании определенных языков или символов.

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

Примечание:в настоящее время существует обновленная версия utf8mb4_unicode_ci вызванный utf8mb4_0900_ai_ci - это основано на изменениях в Unicode версии 9.0, а также, по-видимому, быстрее.Он принимает новую схему именования, согласно которой 0900 является версией Unicode и ai означает, что акцент не чувствителен - как и предыдущий utf8mb4_unicode_ci, ударения в письмах не считаются значимыми.

Преимущества utf8mb4_unicode_ci закончился utf8mb4_general_ci

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

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

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

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

В нелатинских языках, таких как азиатские языки или языки с разными алфавитами, может быть много Еще различия между сортировкой в Юникоде и упрощенным 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 быть двумя, которые пытаются хорошо работать на всех возможных языках, а не на одном конкретном.Различия между этими двумя наборами правил являются предметом данного ответа.Обратите внимание, что новые наборы правил включают 0900 ссылаясь на Unicode 9.0, и unicode_520 ссылка на Unicode 5.2.

И, наконец,, utf8mb4 это, конечно, кодировка символов, используемая внутри компании.В этом ответе я говорю только о кодировках на основе Unicode.

Другие советы

Я хотел знать, в чем разница в производительности между использованием 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

Затем я создал следующие хранимые процедуры для тестирования simple 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_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, но знайте, что он немного устарел.

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

Некоторые подробности (PL)

Как мы можем прочесть здесь (Питер Гулуцан) есть разница при сортировке / сравнении польской буквы "L" (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.Ни одна из этих программ не является лучшей или хуже - это зависит от ваших потребностей.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top