Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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
TINYINT列上的MySQL索引:为什么检查“=0”和检查“is false”之间有区别?_Mysql_Performance_Indexing_Boolean_Tinyint - Fatal编程技术网

TINYINT列上的MySQL索引:为什么检查“=0”和检查“is false”之间有区别?

TINYINT列上的MySQL索引:为什么检查“=0”和检查“is false”之间有区别?,mysql,performance,indexing,boolean,tinyint,Mysql,Performance,Indexing,Boolean,Tinyint,MySQL为查询提供了不同的执行计划,这取决于我是否检查索引的TINYINT字段“为false”或“=0”。表的名称是ordini,意思是“发货”,我希望MySQL使用的索引是shipmentslistrequest 为简单起见,SHOW CREATE ordini I省略了大多数列和索引: CREATE TABLE `ordini` ( `id` int(11) NOT NULL AUTO_INCREMENT, `dataIns` datetime DEFAULT NULL, `h

MySQL为查询提供了不同的执行计划,这取决于我是否检查索引的TINYINT字段“为false”或“=0”。表的名称是ordini,意思是“发货”,我希望MySQL使用的索引是shipmentslistrequest

为简单起见,SHOW CREATE ordini I省略了大多数列和索引:

CREATE TABLE `ordini` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `dataIns` datetime DEFAULT NULL,
  `hasLDV` tinyint(1) NOT NULL DEFAULT '0',
  `isAnnullato` tinyint(1) NOT NULL DEFAULT '0',
  `isEsportatoSAM` tinyint(1) DEFAULT '0',
  `id_azienda_aux` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `dataIns` (`dataIns`),
  KEY `id_azienda_aux` (`id_azienda_aux`),
  KEY `shipmentslistrequest` (`id_azienda_aux`,`isEsportatoSAM`,
                              `hasLDV`,`isAnnullato`,`dataIns`)
) ENGINE=InnoDB AUTO_INCREMENT=5007359 DEFAULT CHARSET=latin1
问题1:

查询2更改:iSportAtom为false:

查询3更改:IsSportAtoSam=0,isAnnullato为false:

我的猜测是:

查询1将正确利用shipmentslistrequest索引

Query2无法在第一列之外使用它,因为我将IseSortatosam与false进行比较,但为什么?。列允许空值这一事实是否有任何相关性?并因此选择不同的索引

Query3将使用第三列之前(包括第三列)的索引,但不会进一步使用,因为“is false”比较,这就是为什么ref列中有三个“const”,这就是为什么连接类型是“ref”而不是“range”,它不会到达索引的日期范围部分。这个解释正确吗

有谁能帮我解决这些问题吗

PS:MySQL版本是5.5.56


PS2:从设计的角度来看,我知道在我没有设计这个系统的那些小列中允许空值是没有意义的。

这只是一个猜测,但我怀疑这是因为is boolean\u值是为了在测试任何数据类型之前将其转换为boolean值而设计的。当列为任何类型的INT时,查询优化器应该能够判断IS FALSE等于=0,然后在第一个查询中使用索引,但显然MySQL没有实现该优化

如果您想进行出色的查询优化,MySQL通常不是首选数据库。

isAnnullato=0允许优化器使用索引


isAnnullato为false要求查询查看每一行并在布尔上下文中计算isAnnullato。

我无法重现该问题,但我没有任何数据。两个建议1.5.5已经很老了;升级2下拉键id_azienda_aux;这是不必要的,因为综合指数。我见过这样的情况,优化器使用较小的索引,尽管较大的索引更好。@RickJames我将删除冗余索引,谢谢。还有一个问题:在问题1的WHERE中添加一个新的比较应该不是问题,对吧?我这样问是因为手册中说,如果列不构成索引最左边的前缀,MySQL就不能使用索引来执行查找,我发现这一措辞令人困惑。在我的查询中添加一个新列会使它不是索引最左边的前缀,但索引仍然会被使用,对吗?因此,最好说查询必须包含索引中列的最左侧前缀,对吗?这些示例可能有助于澄清最左侧前缀混淆:我无法在5.5或更高版本上重现这种情况。我希望IS FALSE等于=0,但我没有证据或反驳。FALSE表示为0,所以我对这个答案表示怀疑。另一方面,TRUE是任何非零值,所以这将是一种不同的情况。
EXPLAIN  select  *
        from  ordini
        where  id_azienda_aux = 92
          and  isEsportatoSAM = 0
          and  isAnnullato = 0
          and  hasLDV = 1
          and  dataIns >= '2020-04-28'
          and  dataIns <  '2020-05-19';

id|select_type|table |type |possible_keys                              |key                 |key_len|ref|rows|Extra      |
--|-----------|------|-----|-------------------------------------------|--------------------|-------|---|----|-----------|
 1|SIMPLE     |ordini|range|dataIns,id_azienda_aux,shipmentslistrequest|shipmentslistrequest|17     |   | 138|Using where|

EXPLAIN   select  *
        from  ordini
        where  id_azienda_aux = 92
          and  isEsportatoSAM is false
          and  isAnnullato = 0
          and  hasLDV = 1
          and  dataIns >= '2020-04-28'
          and  dataIns <  '2020-05-19';

id|select_type|table |type |possible_keys                              |key    |key_len|ref|rows  |Extra      |
--|-----------|------|-----|-------------------------------------------|-------|-------|---|------|-----------|
 1|SIMPLE     |ordini|range|dataIns,id_azienda_aux,shipmentslistrequest|dataIns|9      |   |205920|Using where|
EXPLAIN     select  *
        from  ordini
        where  id_azienda_aux = 92
          and  isEsportatoSAM = 0
          and  isAnnullato is false
          and  hasLDV = 1
          and  dataIns >= '2020-04-28'
          and  dataIns <  '2020-05-19';

id|select_type|table |type|possible_keys                              |key                 |key_len|ref              |rows|Extra      |
--|-----------|------|----|-------------------------------------------|--------------------|-------|-----------------|----|-----------|
 1|SIMPLE     |ordini|ref |dataIns,id_azienda_aux,shipmentslistrequest|shipmentslistrequest|7      |const,const,const| 206|Using where|