Existe um benchmark de desempenho do MySQL para medir o impacto de utf8_unicode_ci versus utf8_general_ci?

12

Eu leio aqui e que usando o utf8_unicode_ci collation garante um melhor tratamento do texto unicode (por exemplo, ele sabe como expandir caracteres como 'para' oe 'para pesquisa e ordenação) comparado com o padrão utf8_general_ci que basicamente apenas retira diacríticos. Infelizmente, ambas as fontes indicam que utf8_unicode_ci é um pouco mais lento que utf8_general_ci .

Então, minha pergunta é: o que significa "um pouco mais lento"? Alguém já executou benchmarks? Estamos falando de um impacto de desempenho de -0,01% ou algo como -25%?

Obrigado pela sua ajuda.

    
por MiniQuark 05.07.2010 / 12:05

2 respostas

7

Bem, eu não encontrei nenhum benchmark na Internet, então eu decidi fazer benchmarks eu mesmo.

Eu criei uma tabela muito simples com 500000 linhas:

CREATE TABLE test(
  ID INT(11) DEFAULT NULL,
  Description VARCHAR(20) DEFAULT NULL
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;

Em seguida, preenchai com dados aleatórios executando este procedimento armazenado:

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

Em seguida, criei os procedimentos armazenados a seguir para fazer um benchmark de SELECT simples, SELECT com LIKE e classificação (SELECT com 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

Nos procedimentos armazenados acima utf8_general_ci, o agrupamento é usado, mas é claro que durante os testes eu usei tanto o utf8_general_ci quanto o utf8_unicode_ci.

Eu chamei cada procedimento armazenado 5 vezes para cada agrupamento (5 vezes para utf8_general_ci e 5 vezes para utf8_unicode_ci) e, em seguida, calculei os valores médios.

Aqui estão os resultados:

benchmark_simple_select () com utf8_general_ci: 9957 ms
benchmark_simple_select () com utf8_unicode_ci: 10271 ms
Neste benchmark usando utf8_unicode_ci é mais lento que utf8_general_ci em 3,2%.

benchmark_select_like () com utf8_general_ci: 11441 ms
benchmark_select_like () com utf8_unicode_ci: 12811 ms
Neste benchmark usando utf8_unicode_ci é mais lento que utf8_general_ci em 12%.

benchmark_order_by () com utf8_general_ci: 11944 ms
benchmark_order_by () com utf8_unicode_ci: 12887 ms
Neste benchmark usando utf8_unicode_ci é mais lento que utf8_general_ci em 7.9%.

    
por 02.03.2013 / 03:50