我有一个四列的表格…
`id` INT(11) NOT NULL AUTO_INCREMENT `tid` INT(11) NOT NULL `cid` INT(11) NOT NULL `name` NVARCHAR(4096) NULL DEFAULT NULL
id 是唯一的主键。其他列不是唯一的。
我想返回具有特定 tid* 和 cid 值并按名称排序的所有 id 值的列表。所以这… ***
select id from myTable where cid = 1 && tid = 1 order by name
该表中大约有125k条记录,大约有50k条恰好符合此条件。所有四个列都有各自的索引。
在我的机器上,查询大约需要140毫秒才能运行。我需要将其降低到20ms左右或更短。我认为解决方案是添加一个新的覆盖索引,该索引针对 cid , tid 和name以此顺序定义。没什么区别。
有任何想法吗?我的覆盖指数设置不正确吗?
我认为查询和表定义本身存在一些问题。
Table.name
您基于存储字符串的列进行排序。为了按字符串排序,必须执行字符串比较。字符串比较通常是一个缓慢的操作,并且鉴于您正在使用的列的大小,很可能会导致明显的性能下降。
我们没有表明您的name专栏内容,并且似乎很难想到一个需要 这么 多字符的实际名称。
name
如果此字符串具有概念上不同的几条数据,则可能的话,应将该列分解为多个单独的列,然后适当地进行规范化。
如果您可以将该列的内容分成多个较小的内容,然后使用它们,则字符串比较尽管仍然很昂贵,但“比较快”,这仅仅是因为所比较的字符串将比现在的字符串短得多。
要考虑的另一件事是,您是否可以通过完全 避免 字符串比较或通过避免尽管定义了索引但仍会导致全表扫描的查询来优化搜索。
为此,您应该考虑explain将查询与查询一起使用,以便更好地了解查询执行计划。
explain
引用文档(我的重点):
根据表,列,索引的详细信息以及WHERE子句中的条件 ,MySQL优化器考虑了许多技术来有效执行SQL查询中涉及的查找。…您的目标是… 如果发现一些低效的操作,则将学习SQL语法和索引技术以改进计划。
您已经澄清了您的name专栏实际上是为用户说明。在这种情况下,我认为您应该考虑以下内容( 除了 已经提到的内容之外):
text