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