MySQL选择看起来很慢但是想不出怎么改进?

我有一个有四列的单人桌子……

 `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是4K char列
>查询按该列排序

您正在根据存储字符串的列进行排序.为了按字符串排序,必须执行字符串比较.字符串比较往往是一个缓慢的操作,并且考虑到您正在使用的列的大小,它很可能会导致明显的性能损失.

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

如果此字符串具有几个概念上不同的数据,则可能应将列拆分为多个单独的列(如果可能),然后根据需要进行标准化.

如果您可以将该列的内容分解为多个较小的列,然后使用它们,字符串比较虽然仍然很昂贵,但“更快”只是因为被比较的字符串将比现在的字符串短得多.

另一件需要考虑的事情是,如果您可以通过完全避免字符串比较来优化搜索,或者通过避免将导致全表扫描的查询来优化搜索,尽管您已经定义了索引.

为此,您应该在查询中使用说明,以便更好地了解Query Execution Plan

引用文档(我的重点):

Depending on the details of your tables, columns, indexes, and the
conditions in your WHERE clause
, the MySQL optimizer considers many
techniques to efficiently perform the lookups involved in an SQL
query. … Your goals are … to learn the SQL syntax and indexing techniques to improve the plan if you see some inefficient operations.

编辑1

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

>将列重命名为与其实际内容相关的内容
>从列中删除索引
>不要使用该列进行搜索,排序或任何其他操作,而不仅仅是选择它来显示它(如果它需要用于其他任何事情,那就非常罕见了,恕我直言.)
>(可选)考虑将列更改为文本类型,您不必担心在没有警告的情况下截断用户文章(除非GUI对用户强制执行相同的输入长度限制)

上一篇:MySQL无法创建外键约束


下一篇:python – 以字符串元组作为索引的Pandas DataFrame