Mysql sql的工作原理<;或>;在sql中,关于使用索引

Mysql sql的工作原理<;或>;在sql中,关于使用索引,mysql,sql,indexing,Mysql,Sql,Indexing,此sql如何使用索引以及此sql如何不使用索引 CREATE TABLE `testtable` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `a` int(11) NOT NULL, `b` int(11) NOT NULL, `c` int(11) NOT NULL, `d` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `idx_abd` (`a`,`b`,`d`) ) ENGINE

此sql如何使用索引以及此sql如何不使用索引

CREATE TABLE `testtable` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `a` int(11) NOT NULL,
  `b` int(11) NOT NULL,
  `c` int(11) NOT NULL,
  `d` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_abd` (`a`,`b`,`d`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

explain select * from testtable where a > 1;
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | testtable | NULL       | ALL  | idx_abd       | NULL | NULL    | NULL |   10 |    80.00 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+


explain select * from testtable where a < 1;
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
| id | select_type | table     | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                 |
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
|  1 | SIMPLE      | testtable | NULL       | range | idx_abd       | idx_abd | 4       | NULL |    1 |   100.00 | Using index condition |
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+

CREATE TABLE`testtable`(
`id`bigint(20)非空自动增量,
`a`int(11)不为空,
`b`int(11)不为空,
`c`int(11)不为空,
`d`int(11)不为空,
主键(`id`),
键'idx_abd'('a','b','d`)
)ENGINE=InnoDB AUTO_INCREMENT=11默认字符集=utf8;
解释从测试表中选择*,其中a>1;
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
|id |选择|类型|表格|分区|类型|可能的|键|键|列|参考|行|过滤|额外|
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
|1 |简单|测试表| NULL | ALL | idx | U abd | NULL | NULL | NULL | 10 | 80.00 |使用where|
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
解释从测试表中选择*,其中a<1;
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
|id |选择|类型|表格|分区|类型|可能的|键|键|列|参考|行|过滤|额外|
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
|1 |简单|测试表| NULL |范围| idx | U abd | idx | U abd | 4 | NULL | 1 | 100.00 |使用索引条件|
+----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+
为什么第一个不能使用索引,而第二个使用索引。
索引在内部是如何工作的?

在第一种情况下,MySQL optimizer(基于统计数据)决定最好进行完整的表扫描,而不是先进行索引查找,然后再进行数据查找

在您的第一个查询中,使用的条件(
a>1
)实际上需要访问11行中的10行。永远记住,MySQL是这样做的(试图将成本降至最低)。这个过程基本上是:

  • 为每个操作分配成本
  • 评估每个可能的计划需要多少操作
  • 把总数加起来
  • 选择总成本最低的计划
  • 现在,
    io\u block\u read\u成本的默认MySQL成本是1。在第一个查询中,大约有两倍的I/O块读取(首先用于索引查找,然后用于数据查找)。因此,如果MySQL决定使用该索引,那么成本大约为20。相反,如果它直接进行表扫描,成本大约为11(所有行上的数据查找)。这就是为什么它决定使用表扫描而不是基于范围的索引扫描

    如果您想获得有关成本分解的详细信息,请将
    EXPLAIN format=JSON
    附加到每个查询并执行它们,如下所示:

    EXPLAIN format=JSON select * from testtable where a > 1;
    
    您还可以看到优化器在锁定特定策略之前是如何比较各种计划的。为此,请执行以下查询:

    /* Turn tracing on (it's off by default): */
    SET optimizer_trace="enabled=on";
    SELECT * FROM testtable WHERE a > 1; /* your query here */
    SELECT * FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
    /* possibly more queries...
     When done with tracing, disable it: */
    SET optimizer_trace="enabled=off";
    

    查看MySQL文档的更多详细信息:

    另一种方法是同时读取索引和数据页。在这样小的数据上,这可能会降低效率(尽管性能上的差异——比如每个查询的持续时间——非常小)

    您的表有10行,它们大概都在一个数据页上。MySQL认为直接读取10行并进行比较更有效


    索引的价值在于当您有较大的表时,尤其是跨多个数据页的表时。一个主要用途是减少正在读取的数据页的数量。

    哦,是的,当我在sql中使用>10时,它表明我使用了索引。谢谢。我学会了一种新的解释sql的方法;在解释中:“使用索引”表示索引是“覆盖”。“使用索引条件”表示引擎测试了其他条件,而不是“处理程序”。