Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/81.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_Sql_Optimization_Indexing - Fatal编程技术网

Mysql 为什么索引的使用依赖于列类型

Mysql 为什么索引的使用依赖于列类型,mysql,sql,optimization,indexing,Mysql,Sql,Optimization,Indexing,我的问题是: SELECT u0_.value AS value0, u1_.property_uri AS property_uri1, count(u0_.id) AS sclr2, u2_.service_id AS sclr3 FROM usc_connection_triple u0_ INNER JOIN usc_pro1_ ON u0_.property_id = u1_.id AND (u1_.status = 1) INNER JOIN usc_account_conne

我的问题是:

SELECT u0_.value AS value0, u1_.property_uri AS property_uri1, count(u0_.id) AS sclr2, u2_.service_id AS sclr3 
FROM usc_connection_triple u0_ 
INNER JOIN usc_pro1_ ON u0_.property_id = u1_.id AND (u1_.status = 1) 
INNER JOIN usc_account_connection u3_ ON u0_.account_connection_id = u3_.id AND (u3_.status = 1) 
INNER JOIN usc_service_subscriber u2_ ON ((u2_.id = u3_.account_1_id OR u2_.id = u3_.account_2_id)) AND (u2_.status = 1) 
WHERE (u1_.create_analytics = '1') AND (u0_.status = 1) GROUP BY u2_.service_id, u0_.property_id, u0_.value;
我已经创建了一个关于u0_(usc_连接_三元组)的索引,其定义如下:

CREATE INDEX `temp` ON usc_connection_triple(property_id, account_connection_id, status, value);
这个复合索引工作得很好,“explain”命令还提示mysql优化器正在使用它,如下所示:


但是,只有当“value”列(类型“varchar”)长度为时,才能查看第一个执行计划,并尝试了解它是如何使用索引的

特别是额外一栏提供了非常有价值的信息:

使用Where

这意味着它需要应用一些
where
子句作为筛选谓词。也就是说,它并不是真的对所有
where
子句使用这个索引,只是对其中的一些子句使用这个索引

键长度=4

key\u len
列中,MySQL告诉我们它真正有效地使用了多少索引。4表示4个字节,通常转换为单个
int
(或类似)列。这意味着,MySQL只能有效地使用索引中的第一列(
property\u id
)。请参阅下面的修复建议

使用索引

返回到附加列。它实际上应该读为“仅使用索引”。这意味着索引恰好包含此查询所需的所有数据(列)。换句话说,查询不引用任何不属于索引的列。因此,MySQL不需要进行额外的IO操作来从实际表中获取更多的列。此功能也称为仅索引扫描。它可以将查询性能提高上百倍

现在是@juergend提到的限制:索引项的最大长度是有限的。对于InnoDB,每列767字节,总计3072字节。但是,如果您使用的是多字节字符集(UTF-8),则这些是字节,如您所观察到的,该数字较小

因此,当您尝试为不适合索引的内容编制索引时,MySQL将自动截断索引项以适合索引。但是,这意味着它不再在索引中存储完整的列,因此它需要额外跳到表以获取完整的列。这可以轻松将查询速度降低100倍:(

最后,最好不要使用这个索引,或者使用另一个恰好更小的索引(如您的情况)

建议

首先使用where部分修复
。查看连接谓词:

INNER JOIN usc_pro1_ ON u0_.property_id = u1_.id AND (u1_.status = 1) 
指数呢

ON usc_connection_triple(property_id, account_connection_id, status, value)
高效的索引使用只能在左边的列中进行。想象一下,一本著名的电话簿通常是按姓、名订购的。现在,尝试查找所有名为“Sarah”的人在这个电话簿中。这里也发生了类似的问题。第一列
property\u id
很好,它在查询中以相等条件提到。但是,下一个索引列
account\u connection\u id
在where子句中根本没有提到。这就是为什么它可以只使用下一列
status
y作为过滤器

因此,第一个想法可能是重新排序索引,如下所示:

ON usc_connection_triple(property_id, status, account_connection_id, value)
这将使使用where
消失(不过,根据MySQL版本的不同,有时不会消失)

您可能甚至会考虑把<代码>状态>代码>,因为它似乎是一个始终存在的WHERE子句。它甚至允许在某些情况下使用索引(不在您的,因为它不是<代码>命令中的第一列> < /Cult>子句)对<代码>属性Type ID /代码>进行排序。

如果无法使查询执行仅索引扫描(额外显示
使用index
),则应从索引中删除
where
子句中未使用的列

参考资料


最大索引长度为255感谢您提供的详细信息!我终于找到了一种方法来获取mysql optimizer使用的索引(按照您的建议更改顺序)。但有趣的是,性能仍然与索引之前相同,根本没有任何改进!对此有何建议?