sql >> データベース >  >> RDS >> Mysql

SQLのバイナリ文字列のハミング距離

    BINARYにデータを保存しているようです columnは、パフォーマンスが低下する可能性のあるアプローチです。適切なパフォーマンスを得る唯一の高速な方法は、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);
    

    私のテストでは、このアプローチを使用すると、BINARYを使用するよりも100倍以上高速になります。 アプローチ。

    FWIW、これは私が問題を説明しているときにほのめかしたコードです。同じことを達成するためのより良い方法を歓迎します(私は特に2進数>16進数>10進数の変換が好きではありません):

    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. DBに接続せずにmysql_real_escape_stringの代わりに

    2. SQLServerからデータベースのリストを取得する

    3. バーコードの生成と読み取り

    4. テーブルをロックせずに巨大なMySQL本番テーブルにインデックスを作成する