Mysql
 sql >> база данни >  >> RDS >> Mysql

Разстояние на Хеминг върху двоични низове в SQL

Изглежда, че съхраняването на данните в BINARY колона е подход, който неизбежно се представя лошо. Единственият бърз начин да получите прилична производителност е да разделите съдържанието на BINARY колона в множество BIGINT колони, всяка от които съдържа 8-байтов подниз от оригиналните данни.

В моя случай (32 байта) това би означавало използване на 4 BIGINT колони и с помощта на тази функция:

CREATE FUNCTION HAMMINGDISTANCE(
  A0 BIGINT, A1 BIGINT, A2 BIGINT, A3 BIGINT, 
  B0 BIGINT, B1 BIGINT, B2 BIGINT, B3 BIGINT
)
RETURNS INT DETERMINISTIC
RETURN 
  BIT_COUNT(A0 ^ B0) +
  BIT_COUNT(A1 ^ B1) +
  BIT_COUNT(A2 ^ B2) +
  BIT_COUNT(A3 ^ B3);

Използването на този подход в моето тестване е над 100 пъти по-бързо от използването на BINARY подход.

FWIW, това е кодът, за който намекнах, докато обяснявах проблема. По-добри начини за постигане на същото нещо са добре дошли (особено не харесвам двоични> шестнадесетични> десетични преобразувания):

CREATE FUNCTION HAMMINGDISTANCE(A BINARY(32), B BINARY(32))
RETURNS INT DETERMINISTIC
RETURN 
  BIT_COUNT(
    CONV(HEX(SUBSTRING(A, 1,  8)), 16, 10) ^ 
    CONV(HEX(SUBSTRING(B, 1,  8)), 16, 10)
  ) +
  BIT_COUNT(
    CONV(HEX(SUBSTRING(A, 9,  8)), 16, 10) ^ 
    CONV(HEX(SUBSTRING(B, 9,  8)), 16, 10)
  ) +
  BIT_COUNT(
    CONV(HEX(SUBSTRING(A, 17, 8)), 16, 10) ^ 
    CONV(HEX(SUBSTRING(B, 17, 8)), 16, 10)
  ) +
  BIT_COUNT(
    CONV(HEX(SUBSTRING(A, 25, 8)), 16, 10) ^ 
    CONV(HEX(SUBSTRING(B, 25, 8)), 16, 10)
  );


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. грешка при използване на mysql_real_escape_string()

  2. MySQL COUNT() и нулеви стойности

  3. Как да актуализирам колоната с тип данни JSON в MySQL 5.7.10?

  4. Използване на MySQL тригери за регистриране на всички промени в таблицата във вторична таблица

  5. Mysql Left Join Null резултат