sql >> Databasteknik >  >> RDS >> Mysql

Hamming avstånd på binära strängar i SQL

Det verkar som att lagra data i en BINARY kolumn är ett tillvägagångssätt som måste prestera dåligt. Det enda snabba sättet att få anständig prestanda är att dela upp innehållet i BINARY kolumn i flera BIGINT kolumner, som var och en innehåller en 8-byte delsträng av originaldata.

I mitt fall (32 byte) skulle detta innebära att man använder 4 BIGINT kolumner och använda denna funktion:

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);

Att använda detta tillvägagångssätt, i mina tester, är över 100 gånger snabbare än att använda BINARY tillvägagångssätt.

FWIW, det här är koden jag antydde när jag förklarade problemet. Bättre sätt att åstadkomma samma sak är välkomna (jag gillar särskilt inte de binära> hex> decimalkonverteringarna):

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. Vad är korrekt JDBC URL-syntax om Oracle-plånböcker används?

  2. CodeIgniter/PHP/MySQL:Hämtar data med JOIN

  3. Mac OS Sierra virtualenv (python 2.7) pip installation mysqlclient fel

  4. Namngivning av viloläge skiljer sig mellan olika operativsystem