我有一个包含2个表的数据库,我必须运行一个简单的查询`
select *
from tableA,tableB
where tableA.user = tableB.user
and tablea.email LIKE "%USER_INPUT%"
其中user_input是必须匹配的tablea.email字符串的一部分。
问题:
该表将携带大约1000万个寄存器并且需要一段时间,ibatis的缓存(据我所知)将仅在前一个查询看起来相同的情况下使用。例如:对于USER_INPUT = john_doe,如果第二个查询再次是john_doe,则缓存将起作用,但如果john_do不起作用(就像我说的那样,据我所知)。
当前,tableA结构是这样的:
id int(11) not_null auto_increment
email varchar(255)not_null
many more fields...
我不知道是否电子邮件,一个255的varchar可能太长并且可能需要更长的时间,因为如果我将它减少到150个字符,例如,响应时间会更短吗?
现在查询花了太长时间......我知道我可以升级到服务器的更多内存,但我想知道是否有其他方法可以改进此代码。
tableA和tableB各有大约30个字段,它们与关系模式上的ID相关。
我要为tableA.email创建一个索引。
想法?
答案 0 :(得分:1)
MySQL不能在LIKE查询上使用索引,其中通配符位于搜索字符串(%query
)之前。
您可以尝试全文搜索。您必须在电子邮件列中添加FULLTEXT索引:
ALTER TABLE tablea
ADD FULLTEXT(email);
从那里你可以修改你的查询
SELECT *
FROM tableA,tableB
WHERE tableA.user = tableB.user
AND MATCH (tablea.email) AGAINST ('+USER_INPUT' IN BOOLEAN MODE)
您必须确保可以使用全文索引。
全文索引只能用于MyISAM表。 (在MySQL 5.6及更高版本中,它们也可以与InnoDB表一起使用。)
答案 1 :(得分:1)
我建议在您的数据库中为该查询运行执行计划。这将说明DB计划如何执行您的查询,以及您正在寻找的是“全表扫描”。我猜你会看到,由于like
子句和索引,电子邮件字段对此部分没有帮助。
如果您需要搜索电子邮件地址的子字符串,则可能需要考虑存储数据的粒度。例如,不像往常一样将电子邮件地址存储在单个字段中,您可以将它们分成两个字段(或者更多),其中“@”之前的所有内容都在一个字段中,而域名在另一个字段中。然后,您可以在不需要like
的情况下搜索任一组件,然后索引会显着加快速度。例如,您可以执行此操作来搜索:
WHERE tableA.email_username = 'USER_INPUT' OR tableA.email_domain = 'USER_INPUT'
当然,你必须连接两个字段才能重新创建电子邮件地址,但我认为iBatis会让你在数据对象中添加一个方法来在一个地方而不是整个应用程序中完成这些工作(已经有一段时间了)因为我使用了iBatis,所以我可能错了。)