Существует ли тест производительности MySQL для измерения влияния utf8_unicode_ci по сравнению с utf8_general_ci?

13

Я читал здесь и там, что использование utf8_unicode_ciсопоставления обеспечивает лучшую обработку текста в Юникоде (например, он знает, как развернуть такие символы, как «œ» в «oe» для поиска и упорядочения) по сравнению со стандартным значением, utf8_general_ciкоторое в основном просто исключает диакритические знаки. К сожалению, оба источника указывают, что utf8_unicode_ciэто немного медленнее, чем utf8_general_ci.

Итак, мой вопрос: что означает «немного медленнее»? Кто-нибудь запускал тесты? Мы говорим о влиянии на производительность -0,01% или, скорее, о -25%?

Спасибо за вашу помощь.

MiniQuark
источник
Что касается теста, почему бы не использовать время запроса? Я могу быть идиотом, но что если вы запустили виртуальную машину и протестировали время запроса для большого сложного запроса для обеих кодировок символов? (Я не видел тестов, сделанных для этого раньше)
Ablue

Ответы:

8

Ну, я не нашел никаких тестов в Интернете, поэтому я решил сделать тесты самостоятельно.

Я создал очень простую таблицу с 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

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

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 мс
В этом тесте с использованием utf8_unicode_ci происходит медленнее , чем utf8_general_ci на 3,2%.

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

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

nightcoder
источник
2

Я не видел никаких тестов, но вы можете запустить свой собственный, используя функцию BENCHMARK :

ЭТАЛОН (количество, выражение)

По совету Мэтью вы можете запустить параллельную установку MYSQL, но учтите, что между различными архитектурами может быть огромное различие (sparc, intel, 32bit, 64bit, ...).

tmow
источник