在MySQL中使用VARCHAR vs INT跨越数百万行

时间:2014-08-13 06:33:39

标签: mysql sql optimization

我有一个表格,里面有大约30,000,000行数据。

表格相对简单:

 +--------------------------------------+
 | TABLE: recipe_locations              |
 +--------------------------------------+
 | INT recipe_id (primary_key)          |
 | TEXT url                             |
 | VARCHAR(128) domain (index)          |
 | VARCHAR(128) tag                     |
 | INT number_ingrediants (index)       |
 +--------------------------------------+

在标签内,我试图把菜的一个主要成分。我想让这种成分可以搜索。

我目前遇到的问题是,在tag列上进行搜索需要相当长的时间。事实上,一些LIKE %...%查询可能需要10秒才能完成,这对于我想要推送到此表的工作负载是不可接受的。

我想知道让另一个表中包含所有主要成分的表更快,并首先搜索tags表,获取ID,然后执行WHERE IN recipe_locations表?

我唯一可以想象的是,如果搜索查询是," a" ( - 标签表中可能存在数十万个匹配项),然后获取标签的所有ID将意味着使用WHERE IN执行子查询,或执行LEFT JOIN。我想知道这是否会妨碍我前面描述的LIKE查询的表现。

1 个答案:

答案 0 :(得分:4)

使用LIKE通过具有30000000条记录的VARCHAR字段进行搜索可能是您在性能方面可以做的最糟糕的事情。还有一个TEXT字段,可能会在每一行上变得很大,这将使它更慢。因此,应该尽可能少地访问该表recipe_locations。如果我是你,我会创建另外两个表:

表:成分

ingrediant_id INTEGER AUTOINCREMENT PRIMARY KEY
ingrediant_name VARCHAR(128)

表recipe_ingrediants(1:n关系,你可能想要那个)

recipe_id INTEGER
ingrediant_id INTEGER

(定义适当的索引)

select
  r.*
from
  recipe_ingrediants ri
left join
  recipe r on r.recipe_id=ri.recipe_id
left join
  ingrediants i on i.ingrediant_id=ri.ingrediant_id
where
  i.ingrediant_name='SALT'
order by
  something

这样查询只会查看最大的表一次。使用适当的索引定义,这将比现在的快得多。