MySQL select看起来很慢,但无法思考如何改进?

MySQL select看起来很慢,但无法思考如何改进?,mysql,sql,indexing,covering-index,Mysql,Sql,Indexing,Covering Index,我有一个四列的表 `id` INT(11) NOT NULL AUTO_INCREMENT `tid` INT(11) NOT NULL `cid` INT(11) NOT NULL `name` NVARCHAR(4096) NULL DEFAULT NULL id是唯一的主键。其他列不是唯一的 我想返回所有id值的列表,这些值具有特定的tid和cid值,并按名称排序。所以这个 select id from myTable where cid = 1 &&

我有一个四列的表

 `id` INT(11) NOT NULL AUTO_INCREMENT   
 `tid` INT(11) NOT NULL
 `cid` INT(11) NOT NULL
 `name` NVARCHAR(4096) NULL DEFAULT NULL
id是唯一的主键。其他列不是唯一的

我想返回所有id值的列表,这些值具有特定的tidcid值,并按名称排序。所以这个

 select id
 from myTable
 where cid = 1 && tid = 1
 order by name
表中大约有125k条记录,大约有50k条恰好符合此标准。所有四列都有单独的索引

在我的机器上,查询运行大约需要140毫秒。我需要把速度降到20毫秒或更高。我认为解决方案是添加一个新的覆盖指数,该指数按照cidtid和name的顺序定义。但没有任何区别


有什么想法吗?我的覆盖索引设置是否不正确?

我认为查询和表定义本身存在一些问题

  • Table.name
    是一个4K字符列
  • 查询正在按该列排序
您根据存储字符串的列进行排序。为了按字符串排序,必须执行字符串比较。字符串比较往往是一个缓慢的操作,考虑到所使用的列的大小,它很可能会导致明显的性能下降

我们没有关于您的
名称
列内容的指示,似乎很难想到需要这么多字符的实际名称

如果这个字符串有几个概念上不同的数据段,那么可能的话,应该将该列分解为多个单独的列,然后根据需要进行规范化

如果您可以将该列的内容拆分为多个较小的内容,然后使用这些内容,那么字符串比较虽然仍然很昂贵,但会“更快”,因为要比较的字符串将比现在的字符串短得多

另一个要考虑的问题是,如果您完全避免字符串比较,或者通过避免会导致全表扫描的查询来优化搜索,尽管您已经定义了索引。 为此,您应该在查询中使用

explain
,以便更好地理解

引用文件(我的重点):

取决于表、列、索引和 在WHERE子句中,MySQL优化器考虑了许多条件 有效执行SQL中涉及的查找的技术 查询你的目标是学习SQL语法和索引技术,以便在发现一些低效操作时改进计划。


编辑1 您已经澄清,您的
名称
列实际上是用于用户注释的。在这种情况下,我认为你应该考虑以下内容(除了已经提到的内容):

  • 将列重命名为与其实际内容相关的内容
  • 从列中删除索引
  • 不要将该列用于搜索、排序或任何其他操作,而只是选择它来显示它(IMHO,如果它需要用于其他任何操作,这将是非常罕见的)
  • 可选地,考虑将该列更改为<代码>文本< /代码>类型,并且您不必担心用户文章在没有警告的情况下被截断(除非GUI对用户执行了相同的输入长度限制)
  • 。 将大大加快查询速度

    但是,这假定
    name
    是一个文明的长度,例如小于255。如果您必须有较长的
    名称
    ,则这是您所能做的最好的选择:

    INDEX(cid, tid)  -- (in either order)
    
    否,“前缀”索引没有帮助:
    索引(cid、tid、名称(99))
    。前缀索引对于排序依据无效

    所有四列都有单独的索引

    单个索引与复合索引不同。有时他们更好;通常不是


    我在我的.

    中提供了更多详细信息。考虑到你的专栏的巨大规模,你的专栏
    name
    的名字被错误地命名了。按4k列排序毫无意义,是的,速度会非常慢。但我认为覆盖索引已经有效地完成了排序,因此在插入和更新时受到影响。当然,选择应该是快速的,因为它看起来只检查索引?取决于您需要什么。它是巨大的。。为什么呢?如果你有一个很好的理由,秒在这里不应该是一个问题。按一个巨大的列排序总是很慢的。您是否尝试对此查询运行
    EXPLAIN
    ,以查看它使用的索引?另外,请记住,每行4K的50k行是200MB。这是需要在20毫秒内处理的巨大数据量。你需要重新思考你在这里要做什么。索引通常有助于提高搜索效率。它可以用来优化排序,但不能保证这样做。说得好。这完美地抓住了问题。“名称”实际上包含用户注释。但你的权利是尺寸可以小得多。99%的情况下,人们输入的字符数不超过100个,因此强制输入更小的字符是可以接受的。我只是试着对这个问题进行“解释”。它的大小为250,使用索引,速度非常快。将其保留为4096个字符会导致它进行表扫描,并且需要相对较长的时间。似乎大小会影响使用的索引。我敢问你为什么在用户笔记上有索引吗?下面的字符串是否值得索引:“我想要一个圣诞风筝”@PhilWright:我认为没有必要为用户笔记创建索引,因为你不应该这样搜索它们。根据与用户的
    id
    关联的注释的
    id
    搜索用户注释。想象一下,如果一本书的索引中有一整章的内容,而不仅仅是标题,那么这将是多么低效。但这正是你在做的
    INDEX(cid, tid)  -- (in either order)