簡體   English   中英

如何加快此BIT_COUNT查詢的漢明距離?

[英]How do I speed up this BIT_COUNT query for hamming distance?

我有一個php腳本,用於檢查從安全攝像機拍攝的2張靜態照片之間的漢明距離。

該表是具有240萬行的mySQL,由一個鍵和4個INT(10)組成。 INT(10)已分別,一起以及與鍵一起被索引,但是我沒有明顯的證據表明任何組合都比其他組合要快。 如果您建議這樣做,我可以再試一次。

通過將圖像轉換為8x16像素來計算漢明權重,並且每四分之一的位存儲在pHash0,pHash1等列中。

我有兩種寫法。 第一種方法是使用嵌套的派生表。 從理論上講,每個派生應檢查的數據要少於其前身。 該查詢是一個准備好的語句,並且? 字段是我要檢查的文件的pHash [0-3]。

Select
    `Key`,
    Bit_Count(T3.pHash3 ^ ?) + T3.BC2 As BC3
  From
    (Select
      *,
      Bit_Count(T2.pHash2 ^ ?) + T2.BC1 As BC2
    From
      (Select
        *,
        Bit_Count(T1.pHash1 ^ ?) + T1.BC0 As BC1
      From
        (Select
          `Key`,
          pHash0,
          pHash1,
          pHash2,
          pHash3,
          Bit_Count(pHash0 ^ ?) As BC0
        From
          files
        Where
          Not pHash0 Is Null And
          Bit_Count(pHash0 ^ ?) < 4) As T1
      Where
        Bit_Count(T1.pHash1 ^ ?) + T1.BC0 < 4) As T2
    Where
      Bit_Count(T2.pHash2 ^ ?) + T2.BC1 < 4) As T3
  Where
    Bit_Count(T3.pHash3 ^ ?) + T3.BC2 < 4

第二種方法更為直接。 它只是一次完成了所有工作。

Select
    `Key`,
  From
    files
  Where
    Not pHash0 is null AND
    Bit_Count(pHash0 ^ ?) + Bit_Count(pHash1 ^ ?) + Bit_Count(pHash2 ^
    ?) + Bit_Count(pHash3 ^ ?) < 4

在大型記錄集上,第一個查詢更快,而在較小的記錄集上,第二個查詢更快,但是對於240萬條記錄,每次比較都不會超過1-1 / 3秒。

您是否看到一種調整此過程以使其更快的方法? 任何建議都可以快速嘗試,例如更改數據類型或索引。

設置為Win7x64,MySQL / 5.6.6和InnoDB,nginx / 1.99,php-cgi / 7.0.0(啟用了zend)。 該腳本是從網頁調用的,並且已關閉緩沖以立即獲得反饋。

編輯:

如果將4個32位整數更改為1 binary(16),可能會更好,將比較值從4更改為1,但是我還必須將4個參數轉換為128位字符,即php不會的 如果有一種快速的方法將它們組合在一起,則可能會浪費更多時間。

編輯接受的答案使速度提高了約500%。 我們的假設的簡要提要:pHash“ A”的比特數將始終在pHash“ B” +/-漢明距離之內。

特別感謝@duskwuff的堅韌和耐心。 歡呼@duskwuff!

編輯這是我最近的查詢:

Select
  files.`Key`, 
  Bit_Count(? ^ pHash0) + Bit_Count(? ^ pHash1) +
  Bit_Count(? ^ pHash2) + Bit_Count(? ^ pHash3) as BC
  From
    files FORCE INDEX (bitcount)
  Where
    bitCount Between ? And ? 
  AND Bit_Count(? ^ pHash0) + Bit_Count(? ^ pHash1) +
  Bit_Count(? ^ pHash2) + Bit_Count(? ^ pHash3) <= ?
  ORDER BY Bit_Count(? ^ pHash0) + Bit_Count(? ^ pHash1) +
  Bit_Count(? ^ pHash2) + Bit_Count(? ^ pHash3)

哪里第4個“?” 表示要檢查的文件的4個32位哈希,接下來的2個“?” 代表該文件的預先計算的比特數+/-所需的漢明距離,最后一個“?” 代表那個漢明距離。 只有將最接近的匹配帶到頂部才需要ORDER BY子句,其中LIMIT 1子句將返回最佳匹配。 bitcount字段上有一個B-TREE索引。

來自240萬個文件的位計數散布成鍾形曲線,極限值為3或4,中心為70,000。 如果給定的文件的位計數為64(最壞的情況),則查找漢明距離為3的文件意味着比較文件的20%(在我的情況下為490,000),而漢明距離為0的比較僅記錄的2.8%(當然是70,000)。

觀察到BIT_COUNT(a ^ b)下面BIT_COUNT(a)BIT_COUNT(b) (也就是說,它始終至少等於該差,並且可能更大。)如果您預先計算了每一行的總位數,則可以使用它來排除總位數與實際值相差太遠的行您的目標。 更好的是,您可以在該列上創建索引,並且將使用該索引。

我所想到的將是以下方面的東西:

ALTER TABLE files ADD COLUMN totalbits INTEGER;
CREATE INDEX totalbits_index ON files (totalbits);

UPDATE files SET totalbits = BIT_COUNT(pHash1) + BIT_COUNT(pHash2)
                           + BIT_COUNT(pHash3) + BIT_COUNT(pHash4);

SELECT `Key` FROM files WHERE (totalbits BETWEEN … AND …) AND …

請注意,有了這個適當的位置,就無需將散列拆分為四個大塊。 將它們組合回一列將使事情變得容易。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM