Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/62.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_Optimization_Indexing_Distinct - Fatal编程技术网

Mysql 可以使用哪些索引来改进此查询?

Mysql 可以使用哪些索引来改进此查询?,mysql,optimization,indexing,distinct,Mysql,Optimization,Indexing,Distinct,此查询选择特定日期范围内的所有唯一访客会话: select distinct(accessid) from accesslog where date > '2009-09-01' 我在以下字段上有索引: 访问ID 日期 其他一些领域 下面是解释的内容: mysql> explain select distinct(accessid) from accesslog where date > '2009-09-01'; +----+-------------+--------

此查询选择特定日期范围内的所有唯一访客会话:

select distinct(accessid) from accesslog where date > '2009-09-01'
我在以下字段上有索引:

  • 访问ID
  • 日期
  • 其他一些领域
下面是解释的内容:

mysql> explain select distinct(accessid) from accesslog where date > '2009-09-01';
+----+-------------+-----------+-------+----------------------+------+---------+------+-------+------------------------------+
| id | select_type | table     | type  | possible_keys        | key  | key_len | ref  | rows  | Extra                        |
+----+-------------+-----------+-------+----------------------+------+---------+------+-------+------------------------------+
|  1 | SIMPLE      | accesslog | range | date,dateurl,dateaff | date | 3       | NULL | 64623 | Using where; Using temporary |
+----+-------------+-----------+-------+----------------------+------+---------+------+-------+------------------------------+


mysql> explain select distinct(accessid) from accesslog;
+----+-------------+-----------+-------+---------------+----------+---------+------+---------+-------------+
| id | select_type | table     | type  | possible_keys | key      | key_len | ref  | rows    | Extra       |
+----+-------------+-----------+-------+---------------+----------+---------+------+---------+-------------+
|  1 | SIMPLE      | accesslog | index | NULL          | accessid | 257     | NULL | 1460253 | Using index |
+----+-------------+-----------+-------+---------------+----------+---------+------+---------+-------------+
为什么带有date子句的查询不使用accessid索引

在某些日期范围内,我是否可以使用其他索引来加速对不同accessid的查询

编辑分辨率

accessid
上的列宽从varchar 255减少到char 32,将查询时间缩短了约75%

添加
date+accessid
索引对查询时间没有影响

为什么带有date子句的查询不使用accessid索引

因为使用日期索引更有效。这是因为它可能会更快地缩减搜索空间

至少有一个DBMS(DB2/z,我对MySQL不太了解)会受益于date+accessid上的索引,因为访问ID将在该索引中的日期内排序。DBMS将使用date+accessid键有效地使用where子句缩减搜索空间,并在该空间内返回不同的accessid值


MySQL是否那么聪明,我不知道。我的建议是试试看(这是大多数DB优化问题的最佳答案)。

查询使用“日期”索引,因为这是where子句中使用的

这是唯一明智的选择,如果它使用accessid索引,则需要读取所有accessid行,然后检查它之前的日期,然后才确定它是否不同


如果这是一个非常大的表,那么date和accessid上的复合索引可能会有所帮助。

我没有办法测试它,但我肯定会尝试添加一个跨越accessid和date的索引


索引优化,如果经常像炼金术。不同的DBM表现不同,有时您需要简单地尝试(并失败)各种组合。我不是说不可能推理。在许多情况下是这样的,但在某种程度上是这样的。通常,遵循你的直觉更快更容易。

你的问题是你的条件是一个范围子句(在日期列上)

date->accessid的多列索引可能对这种情况没有帮助,因为MySQL不能在范围条件之后使用索引列。理论上,他们应该能够使用它来覆盖这种情况下的计算,但这似乎是MySQL的一个缺点,我从来没有在这种情况下成功地使用多列索引

您可以尝试在(date,accessid)上创建一个索引,希望它能够使用它来覆盖查询(这样您就不需要访问任何表),但我不抱太大希望。你能做的不多

编辑:

我的回答是有礼貌的,如果您必须进行认真的MySQL开发,那么它是值得的

为什么带有date子句的查询不使用accessid索引

因为使用日期索引可以忽略表中的大部分数据。很有可能,该表保存的大部分是历史数据,并且其中很多引用的日期比当前月初早得多,因此日期标准是有选择性的,允许优化器忽略大部分数据,从而减少了优化器的工作量

如果它使用accessid索引,它还必须读取每一行(以及每个索引条目),以查看日期是否符合搜索条件。这意味着读取整个索引和整个表——事实上,在上下文中忽略索引会更好,但我从“if it used the accessid index”开始

在某些日期范围内,我是否可以使用其他索引来加速对不同accessid的查询

根据优化器的复杂程度,索引(date,accessid)可能会有所改进。它可以在索引的前导列上进行范围搜索,尾随列意味着它不必引用表中的数据来建立accessid—信息在索引中。因此,这可能会将访问索引和表的查询转换为只访问索引的查询,这将减少所需的I/O量,从而提高查询的性能


如果您有其他条件需要来自其他列的数据,或者您需要返回的不仅仅是唯一的accessid值,那么您最终将读取部分表数据;与扫描整个表相比,这可能仍然是一个胜利。

(日期,accessid)
上建立索引可能会有所帮助。但是,在调整索引之前,我建议检查
accessid
列的类型
EXPLAIN
说这个键有257字节长,这对于ID列来说似乎太多了。您是否使用
VARCHAR(256)
作为
accessid
?如果是这样,你就不能用一种更紧凑的字体吗?如果它是一个数字,它应该是
INT
SMALLINT
BIGINT
,任何适合您需要的)如果它是一个字母数字ID,它真的可以是256个字符长吗?如果它的长度是固定的,你不能用
CHAR
(例如
CHAR(32)
)来代替吗?

啊,好主意。我们使用的accessid是一个32个字符的字符串,例如94a1d523fac45e589e7d8884332fa9b3。我将缩小此字段的大小。是的,添加date+accessid索引没有任何效果。真倒霉