4

所以我在 MySQL 控制台中运行以下命令作为控制测试,看看是什么阻碍了我的查询速度。

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 输出:

在此处输入图像描述

并且没有 CAST:

在此处输入图像描述

解释扩展:

在此处输入图像描述

4

1 回答 1

6

MySQL 如何使用索引中所述:

MySQL 对这些操作使用索引:

[删除]
  • 在执行连接时从其他表中检索行。如果将列声明为相同的类型和大小,MySQL 可以更有效地使用列上的索引。在这种情况下,如果它们被声明为相同的大小,则认为它们是相同的VARCHARCHAR例如,VARCHAR(10)CHAR(10)大小相同,但VARCHAR(10)CHAR(15)不同。

    如果值不能在没有转换的情况下直接比较,则不同列的比较可能会阻止使用索引。假设将数值列与字符串列进行比较。对于给定值(例如1数字列),它可能与字符串列中的任意数量的值(例如'1'' 1''00001'或)进行比较'01.e1'。这排除了对字符串列使用任何索引。

在您的情况下,您试图加入子字符串(一个表中的字符串列)和另一个表中的字符串列之间的比较。索引可用于此操作,但比较是按字典顺序执行的(即,将操作数视为字符串,即使它们表示数字)。

通过将一侧显式转换为整数,以数字方式(根据需要)执行比较 - 但这需要 MySQL隐式转换字符串列的类型,因此它无法使用该列的索引。

您遇到了这个障碍,因为您的架构设计不佳。您应该努力确保所有列:

  1. 使用与其内容最相关的数据类型进行编码;和

  2. 只包含一条信息——请参阅在数据库列中存储分隔列表真的那么糟糕吗?

至少,你bbva_job.emplid应该是一个整数;并且您bbva_deductions.employee_id应该拆分,以便将其部分存储在单独的(适当类型的)列中。使用适当的索引,您的查询将大大提高性能。

于 2013-07-24T06:18:06.287 回答