Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Odległość Hamminga na ciągach binarnych w SQL

Wygląda na to, że przechowywanie danych w pliku BINARY kolumna jest podejściem, które ma słabe wyniki. Jedynym szybkim sposobem na uzyskanie przyzwoitej wydajności jest podzielenie zawartości pliku BINARY kolumna w wielu BIGINT kolumny, z których każda zawiera 8-bajtowy podciąg oryginalnych danych.

W moim przypadku (32 bajty) oznaczałoby to użycie 4 BIGINT kolumn i za pomocą tej funkcji:

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

Korzystanie z tego podejścia w moich testach jest ponad 100 razy szybsze niż użycie BINARY podejście.

FWIW, to jest kod, do którego sugerowałem, wyjaśniając problem. Lepsze sposoby osiągnięcia tego samego są mile widziane (szczególnie nie lubię konwersji binarnych> szesnastkowych> dziesiętnych):

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. Wstaw do wielu tabel w jednym zapytaniu

  2. Wydajność neo4j w porównaniu do mysql (jak można poprawić?)

  3. tabela aktualizuje puste miejsca, gdy użytkownik nie wpisuje niczego w polu tekstowym

  4. Uzyskaj dostęp do bazy danych MySQL w Electronie

  5. Połączenie wewnętrzne laravel 5.2