2013-07-24 56 views
4

所以我在MySQL控制檯中運行以下控制測試以查看阻礙查詢速度的因素。MySQL CAST肯定需要它的甜蜜時間

SELECT bbva_deductions.ded_code, SUBSTRING_INDEX(bbva_deductions.employee_id, '-' , -1) AS tt_emplid, 
      bbva_job.paygroup, bbva_job.file_nbr, bbva_deductions.ded_amount 
      FROM bbva_deductions 
      LEFT JOIN bbva_job 
      ON CAST(SUBSTRING_INDEX(bbva_deductions.employee_id, '-' , -1) AS UNSIGNED) = bbva_job.emplid LIMIT 500 

它持續大約4秒鐘運行。 (只有500行似乎非常高)。

只需去除的CAST部分加入該下降到0.01秒......

爲什麼地球上是Mr.CAST這麼慢?我在做什麼來激怒MySQL神?

編輯:

如這裏要求的是EXPLAIN輸出:

enter image description here

而且沒有CAST:

enter image description here

EXPLAIN EXTENDED:

enter image description here

+0

結果已過帳 –

+0

新輸出已發佈 –

+0

我剛剛嘗試過,它能夠使用索引查找就好。 (有意義的,因爲它只是一個SELECT字段而不是該鍵的一部分)。我也在使用CAST()的時候對查詢進行了EXPLAIN EXTENDED嘗試,並得到了以下消息: 由於字段'emplid'上的類型或排序規則轉換,不能在索引'emplid'上使用ref訪問' –

回答

6

由於How MySQL Uses Indexes下記載:

MySQL使用索引這些操作:

[ deletia ]
  • 其它表執行連接時檢索行。如果它們被聲明爲相同的類型和大小,MySQL可以更有效地在列上使用索引。在這種情況下,如果它們被聲明爲相同大小,則認爲VARCHARCHAR是相同的。例如,VARCHAR(10)CHAR(10)的大小相同,但是VARCHAR(10)CHAR(15)不是。

    不同列的比較可能會阻止使用索引,如果不能直接比較值而不進行轉換。假設數字列與字符串列進行比較。對於數字列中的給定值(例如1),它可能會與字符串列中的任意數量的值進行比較,例如'1',' 1','00001''01.e1'。這排除了字符串列的任何索引的使用。

在你的情況,你試圖加入的(一個表中的字符串列)的一個子和另一個表中的字符串列之間的比較。索引可用於此操作,但是按字典順序執行比較(即將操作數視爲字符串,即使它們表示數字)。

通過明確地將一邊轉換爲一個整數,比較以數字方式執行(根據需要) - 但這需要MySQL到implicitly convert the type的字符串列,因此無法使用該列的索引。

由於您的模式設計不佳,您已經擊中了這個路障。您應該努力確保所有列:

  1. 使用與其內容最相關的數據類型進行編碼;和

  2. 只包含一個資料片—看到Is storing a delimited list in a database column really that bad?

至少,你bbva_job.emplid應該是一個整數。並且你的bbva_deductions.employee_id應該被拆分,以便它的部分被存儲在單獨的(適當類型的)列中。使用適當的索引,您的查詢將更具性能。

+0

+1好答案。 – peterm