Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
mysql不使用索引?_Mysql_Indexing - Fatal编程技术网

mysql不使用索引?

mysql不使用索引?,mysql,indexing,Mysql,Indexing,我有一个表,表中有诸如word、a、E、U等列。。这些带有X_uu的列是tinyint,其值为单词中特定字母存在的次数(以帮助以后优化通配符搜索查询) 总共有252k行。如果我像u_uu0那样搜索,我会得到6万行。但是如果我解释一下这个选择,它会说有225k行要通过,没有索引。为什么?列被添加为索引。为什么它不说有60k行要通过,而可能的关键是U_u2; 在表中列出索引(也奇怪的是,其他索引被分组在一个索引下) 相比之下,如果我运行query:whereid>250000,我会得到2983个

我有一个表,表中有诸如word、a、E、U等列。。这些带有X_uu的列是tinyint,其值为单词中特定字母存在的次数(以帮助以后优化通配符搜索查询)

总共有252k行。如果我像u_uu0那样搜索,我会得到6万行。但是如果我解释一下这个选择,它会说有225k行要通过,没有索引。为什么?列被添加为索引。为什么它不说有60k行要通过,而可能的关键是U_u2;

在表中列出索引(也奇怪的是,其他索引被分组在一个索引下)

相比之下,如果我运行query:whereid>250000,我会得到2983个结果,如果我解释了这一点,select会说有2982行和键要主要使用

顺便说一句,如果我按U_U分组,我会得到以下结果:(但可能没什么大不了的,因为我已经说过查询会返回60k个结果)

编辑:

如果我创建列U(varchar(1))并更新U='U',其中U_U>0,那么如果我选择U='U',我也会得到60k行(显然),但是如果我解释了,我会得到以下结果:


仍然不太好(第120k行不是第60k行),但至少比前一种情况下的第225k行好。虽然这个解决方案比第一个解决方案要简单一些,但可能效率更高。

您正在询问后端查询优化器。特别是,您会问:“它如何选择访问路径?为什么在这里索引而在那里索引?”

让我们想想那个优化器。这是什么?预期中经过的时间。它有一个模型,用于计算顺序读取和随机读取的时间,以及查询选择性,即查询返回的预期行数。它从几个可选的访问路径中选择一个似乎需要最少运行时间的路径

您的
id>250000
查询有几个方面:

  • 良好的选择性,因此结果集中出现的行不到1%
  • id
    是主键,因此导航到btree中的正确位置后,所有列都立即可用
  • 这导致优化器计算索引访问路径的预期运行时间远小于tablescan的预期时间

    另一方面,您的
    u_>0
    查询的选择性非常差,将近四分之一的行拖到结果集中。此外,该索引不是将所有列值复制到结果集中的
    *
    需求的覆盖索引。因此,优化器预测它必须读取四分之一的索引块,然后读取它们所指向的所有数据行块。因此,与tablescan相比,我们必须从磁盘读取更多的块,它们将是随机读取,而不是顺序读取。这两种方法都反对使用索引,因此选择tablescan是因为它最便宜。另外,请记住,通常在单个磁盘块或单个读取请求中可以容纳多行。如果它总是选择索引访问路径,即使在索引磁盘I/O需要更长时间的情况下,我们也会称之为悲观主义者

    简要建议
    当查询具有良好的选择性时,在单个列上使用索引,返回的行远远少于关系行的1%。当您的查询选择性较差,并且您愿意进行空间与时间的权衡时,请使用表扫描。

    我的经验是,如果您的查询选择表中大约25%的行,则MySQL会选择表扫描,即使您正在搜索的列上有索引

    这样做的原因是,在InnoDB中使用辅助索引比使用主索引要多做一些工作

  • 在二级索引中查找值,如
    u\u
    上的索引
  • 读取索引项,并查找存储
    u\u
    中该值的行的相应主键值
  • 按主键查找行
  • 实际上,通过辅助键进行查找的工作量至少是原来的两倍。如果您最终匹配了表中的一小部分行,并且在某些情况下辅助索引对查询非常重要,那么这不是问题。因此,不要不愿意使用二级索引

    但是如果您的查询匹配了太多的行,并且这成为了表的很大一部分,那么只从开始到结束扫描表的工作量就会减少

    打个比方,为什么书后面的索引中没有“the”这个词呢?因为条目自然会列出书中的每一页,如果你参考索引,然后用它引导你进入书的主要部分的每一页,那将是一种浪费。你要是读这本书就好了

    MySQL没有任何官方文档记录的选择表扫描而不是索引搜索的阈值。25%的数字只是我的经验(实际上有时似乎接近21%,但我对代码了解不够,无法准确理解阈值是如何计算的)

    我见过这样的情况:匹配的行的比例非常接近实现中的阈值,优化器的行为实际上可以从一个查询切换到下一个查询,从而导致高度可变的性能

    如果这种情况适用于您,您可以使用使MySQL的优化器假装tablescan非常昂贵,并且它应该更喜欢索引而不是tablescan。这是通过
    FORCE INDEX
    提示完成的

    SELECT * FROM words FORCE INDEX(U_) WHERE U_ > 0
    

    我仍然尝试保守地使用索引提示。除了极少数情况外,它们不是必需的,使用索引提示意味着您的查询必须包含索引名。这使得在不破坏应用程序代码的情况下很难更改索引。

    Hello。如果我在列上添加索引,我希望它将大大加快“访问路径”的速度,并且它还将在描述查询中声明将使用索引以及扫描的总计数