MySQL查询需要很长时间。我尝试了许多查询的变体,但似乎没有任何东西影响查询速度

MySQL查询需要很长时间。我尝试了许多查询的变体,但似乎没有任何东西影响查询速度,mysql,sql,join,Mysql,Sql,Join,以下是我目前的查询和结构数据: SELECT * FROM gmm_sql as a LEFT JOIN usds as b ON a.dp_id = b.dp_id LEFT JOIN usdsown as c ON b.dp_id = c.dp_id WHERE a.comm like '%tree%' gmm_sql:21个字段。所有字段varchar从20到255混合。4882项记录。 usds:7块地。所有字段varchar从20到255混合。304713

以下是我目前的查询和结构数据:

   SELECT * 
     FROM gmm_sql as a
LEFT JOIN usds as b ON a.dp_id = b.dp_id
LEFT JOIN usdsown as c ON b.dp_id = c.dp_id 
    WHERE a.comm like '%tree%'
gmm_sql:21个字段。所有字段varchar从20到255混合。4882项记录。 usds:7块地。所有字段varchar从20到255混合。304713项记录。 播种:14块地。所有字段varchar从20到255混合。107606项记录。 我已经确认有手动匹配。我正在使用MySQL工作台运行这些查询测试。查询只会持续运行10分钟,不会停止

我做错什么了吗

以下是解释输出:

id  select_type table   type    possible_keys   key key_len ref rows    Extra 
1   SIMPLE  a   ALL NULL    NULL    NULL    NULL    3973    Using where
1   SIMPLE  b   ALL dp_id   NULL    NULL    NULL    304345  
1   SIMPLE  c   ALL NULL    NULL    NULL    NULL    105711  

假设id字段已编制索引,这仍然可能是一个庞大的数据集。然后在带有通配符的varchar上有一个where子句。。。这将导致对整个结果集进行完整的表扫描,并否定a.comm字段上的任何索引


只是好奇,但是你能通过将select*改为'select counta.comm'并删除where子句来测试它吗。如果它仍然需要花费很长时间,那么它就是where子句,否则它就是结果集的构建。

假设id字段被索引,这仍然可能是一个巨大的数据集。然后在带有通配符的varchar上有一个where子句。。。这将导致对整个结果集进行完整的表扫描,并否定a.comm字段上的任何索引

只是好奇,但是你能通过将select*改为'select counta.comm'并删除where子句来测试它吗。如果它仍然需要花费很长时间,那么它就是where子句,否则它就是结果集的构建。

在gmm_sql.gmm上建立全文索引。+确保所有外键都已编入索引

其中,类似于“%tree%”的.comm是对数据进行的成本最高的操作。你有文字做全表扫描。普通索引不够,因为在匹配序列的开头有通配符

或者,如果您的数据库不支持这种类型的索引,您可以使用lucene或sphynx。

在gmm_sql.gmm上创建全文索引。+确保所有外键都已编入索引

其中,类似于“%tree%”的.comm是对数据进行的成本最高的操作。你有文字做全表扫描。普通索引不够,因为在匹配序列的开头有通配符


或者,如果您的数据库不支持这种类型的索引,您可以使用lucene或sphynx。

我看到的第一个争论点是:

WHERE a.comm like '%tree%'
即使在GMM_SQL.comm上有索引,对字符串左侧进行通配符也会使索引无效。虽然这是可行的,但它确实是搜索数据类型与字符串相关的内容的最差方法

全文搜索是在字符串中查找内容的首选方法。但是IIRC,MySQL仍然要求表是MyISAM

下一点是:

SELECT *
这将返回所有联接表中的所有列。SELECT子句应仅包含实际需要的列,因为:

您返回的数据比需要的多 数据类型确实会影响性能,例如:如果其中一列是很长的字符串,或者是二进制/二进制数据
第三,你的加入标准。数据类型越小,查询速度越快。我假设任何id为INT的东西都意味着INT。如果不需要,就不要使用BIGINT。

我看到的第一个争论点是:

WHERE a.comm like '%tree%'
即使在GMM_SQL.comm上有索引,对字符串左侧进行通配符也会使索引无效。虽然这是可行的,但它确实是搜索数据类型与字符串相关的内容的最差方法

全文搜索是在字符串中查找内容的首选方法。但是IIRC,MySQL仍然要求表是MyISAM

下一点是:

SELECT *
这将返回所有联接表中的所有列。SELECT子句应仅包含实际需要的列,因为:

您返回的数据比需要的多 数据类型确实会影响性能,例如:如果其中一列是很长的字符串,或者是二进制/二进制数据
第三,你的加入标准。数据类型越小,查询速度越快。我将假设任何id都意味着INT。如果不需要,请不要使用BIGINT。

如果字段都是var_字符,那么这可能不是一个好的设计。您是否创建了任何索引?请在您的问题后附加一个EXPLAIN的输出,以便查询:我首先查看EXPLAIN输出。如果在那些dp_id列上没有索引,那么这些联接将非常昂贵。因此,在“like”开头的“%”比后面的时间要长得多。如果你颠倒了字段的内容,例如“eert”,你可以使用…像“eert%”这样的网站我在上面添加了解释输出。如果字段都是var_字符,那可能不是好的设计。您是否创建了任何索引?请在您的问题后附加一个EXPLAIN的输出,以便查询:我首先查看EXPLAIN输出。那些工作
如果在那些dp_id列上没有索引,那么ns将非常昂贵。因此,在“like”开头的“%”比后面的时间要长得多。如果你颠倒了字段的内容,例如“eert”,你可以使用…像“eert%”这样的网站,我在上面添加了解释输出。