sql >> Database >  >> RDS >> Mysql

Hamming-afstand op binaire strings in SQL

Het lijkt erop dat het opslaan van de gegevens in een BINARY column is een aanpak die zeker slecht zal presteren. De enige snelle manier om fatsoenlijke prestaties te krijgen, is door de inhoud van de BINARY . te splitsen kolom in meerdere BIGINT kolommen, die elk een 8-byte substring van de originele data bevatten.

In mijn geval (32 bytes) zou dit betekenen dat ik 4 BIGINT . gebruik kolommen en met behulp van deze functie:

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

Het gebruik van deze aanpak is bij mijn testen meer dan 100 keer sneller dan het gebruik van de BINARY benadering.

FWIW, dit is de code waarnaar ik hintte terwijl ik het probleem uitlegde. Betere manieren om hetzelfde te bereiken zijn welkom (ik hou vooral niet van de binaire> hex> decimale conversies):

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. SQL-query om het aantal wederzijdse vrienden te vinden, gegeven een tabel met persoon, vriendenpaar

  2. PHP MYSQL multidimensionale array

  3. Entiteitsframework PostgreSQL

  4. Hoe de MySQL-opgeslagen procedure van Rails aan te roepen?