- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
首先,我将描述问题域的简化版本。
有表strings
:
CREATE TABLE strings (
value CHAR(3) COLLATE utf8_unicode_ci NOT NULL,
INDEX(value)
) ENGINE=InnoDB;
如您所见,它有一个 CHAR(3)
列的非唯一索引。
该表是使用以下脚本填充的:
CREATE TABLE a_variants (
letter CHAR(1) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=MEMORY;
INSERT INTO a_variants VALUES -- 60 variants of letter 'A'
('A'),('a'),('À'),('Á'),('Â'),('Ã'),('Ä'),('Å'),('à'),('á'),('â'),('ã'),
('ä'),('å'),('Ā'),('ā'),('Ă'),('ă'),('Ą'),('ą'),('Ǎ'),('ǎ'),('Ǟ'),('ǟ'),
('Ǡ'),('ǡ'),('Ǻ'),('ǻ'),('Ȁ'),('ȁ'),('Ȃ'),('ȃ'),('Ȧ'),('ȧ'),('Ḁ'),('ḁ'),
('Ạ'),('ạ'),('Ả'),('ả'),('Ấ'),('ấ'),('Ầ'),('ầ'),('Ẩ'),('ẩ'),('Ẫ'),('ẫ'),
('Ậ'),('ậ'),('Ắ'),('ắ'),('Ằ'),('ằ'),('Ẳ'),('ẳ'),('Ẵ'),('ẵ'),('Ặ'),('ặ');
INSERT INTO strings
SELECT CONCAT(a.letter, b.letter, c.letter) -- 60^3 variants of string 'AAA'
FROM a_variants a, a_variants b, a_variants c
UNION ALL SELECT 'BBB'; -- one variant of string 'BBB'
因此,它包含 216000 个无法区分的(根据 utf8_unicode_ci
排序规则)字符串“AAA”的变体和字符串“BBB”的一个变体:
SELECT value, COUNT(*) FROM strings GROUP BY value;
+-------+----------+
| value | COUNT(*) |
+-------+----------+
| AAA | 216000 |
| BBB | 1 |
+-------+----------+
由于 value
被索引,我希望以下两个查询具有相似的性能:
SELECT SQL_NO_CACHE COUNT(*) FROM strings WHERE value = 'AAA';
SELECT SQL_NO_CACHE COUNT(*) FROM strings WHERE value = 'BBB';
但实际上第一个比第二个慢 300 倍!见:
+----------+------------+---------------------------------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+---------------------------------------------------------------+
| 1 | 0.11749275 | SELECT SQL_NO_CACHE COUNT(*) FROM strings WHERE value = 'AAA' |
| 2 | 0.00033325 | SELECT SQL_NO_CACHE COUNT(*) FROM strings WHERE value = 'BBB' |
| 3 | 0.11718050 | SELECT SQL_NO_CACHE COUNT(*) FROM strings WHERE value = 'AAA' |
+----------+------------+---------------------------------------------------------------+
-- 为了确定,我在这里运行了两次“AAA”查询。
如果我更改索引列的大小或将其类型更改为 VARCHAR
,性能问题仍然会出现。同时,在类似的情况下,但当非唯一索引不是 CHAR
/VARCHAR
(例如 INT
)时,查询速度与预期一样快.
那么,问题是为什么在使用 CHAR
/VARCHAR
索引时 MySQL 查询的性能如此糟糕?
我有强烈的感觉,MySQL 对索引键匹配的所有值进行全线性扫描。但是,当它只能返回匹配行的计数时,为什么要这样做呢?我是否遗漏了什么,而那是真正需要的?或者这是 MySQL 优化器的一个可悲的缺点?
最佳答案
很明显,问题在于查询正在进行索引扫描。另一种方法是进行两次索引查找,查找相同的第一个和最后一个值,然后使用索引中的元信息进行计算。根据您的观察,MySQL 可以做到这两点。
这个答案的其余部分是猜测。
性能“仅”慢 300 倍,而不是慢 200,000 倍的原因是读取索引的开销。实际上,与所需的其他操作相比,扫描条目的速度相当快。
在比较方面,数字和字符串之间存在根本区别。引擎可以只查看两个数字的位表示并识别它们是相同还是不同。不幸的是,对于字符串,您需要考虑编码/排序规则。我认为这就是它需要查看值的原因。
如果您有 216,000 个 完全 相同字符串的副本,那么 MySQL 将能够使用索引中的元数据进行计数。换句话说,索引器足够聪明,可以使用元数据进行精确相等比较。但是,它不够聪明,无法考虑编码。
关于mysql - 为什么使用 CHAR/VARCHAR 索引时 MySQL 查询的性能如此糟糕?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30439959/
我在 presto 中有表,名为(“mappings”)的列将键值对作为字符串 从 hello 中选择映射; 例如:{“foo”:“baar”,“foo1”:“bar1”} 我想将“映射”列转换为 M
我总是会在表格的特定列中输入 20 个字符的内容。 我需要此列是唯一的。 如果我将此列设置为 varchar(255) 而不是 varchar(20),SELECT 查询的速度会有任何差异吗? (输入
我在 the Dapper .NET project home page 上发现了以下评论. Dapper supports varchar params, if you are executing
我有以下代码。 Case 语句将列出的数字转换为文本并将其余代码转换为 NULL,但我不断收到以下错误:将 VARCHAR 值“RDG5”转换为数据类型 INT 时转换失败。 RDG5 是被转换为 N
运行此脚本时出现以下错误。我尝试过使用以下内容:整理 Latin1_General_CI_AS。请问可以排序吗?谢谢 Msg 457, Level 16, State 1, Line 8 Implic
是否可以将 SQL Server 2008 数据库中的列类型从 varchar(255) 更改为 varchar(MAX),而无需删除表并重新创建? 每次我尝试使用它来执行此操作时,SQL Serve
每次我对选择 varchar(max) 或 varchar(fix) 数据类型感到困惑。假设我有一个大约 5000 个 varchar 的数据列。列不是 null 类型。 我应该将其设置为 varch
您好,我遇到问题,我的 friend 拒绝更改字段的数据类型,所以我在使用 order by 时遇到问题,这里是示例数据 04-07-2016(mm-dd-yyyy) 和字段名称名为 regis_da
对于文字游戏,我正在尝试向 VARCHAR 数组添加 CHECK 约束: CREATE TABLE words_games ( gid SERIAL PRIMARY KEY,
我有一个 varchar 字段,其内容如下: a,b,c,d e,d,a,c b,q,d,e 我需要执行一个查询,仅选择具有与输入字符串相等的元素的字段的行。 前输入:c,a 选择的行: a,b,c,
大家好,我计划创建包含 10 列的表,该表应该至少有 10,000,000 行,并且在其中,我将有列 description - VARCHAR(600) 和索引。 所以问题是,在该列上查询 LIKE
我读过这个question关于MySQL中VARCHAR(254)和VARCHAR(255)的区别。 HiveQL 中是否有必须考虑的类似内容?也许 HiveQL 实现了一些类似于 MySQL 的存储
在 MySQL 中,VARCHAR(1024) 和 VARCHAR(512) 有什么区别?如果我的项目永远不会超过 512 个字符,那么使用 VARCHAR(1024) 我会失去什么? 最佳答案 不知
由于 Varchar 字段的存储要求基于输入的字符串的实际长度,将每个 Varchar 字段指定为最大可能的缺点是什么:Varchar (65535)?那么,除了最大字段 > 255 个字符的 1 个
我正在尝试搜索具有数据类型 map(varchar,varchar) 的列。现在访问列的一种方法是使用这个结构,name_of_column[' key '],它将给出该键的值。但我想知道什么是可能的
快速提问。如果我将使用十进制字段限制或十六进制(比如 16、32、64 而不是 10、20、50),从存储数据的角度来看是否重要? 我问是因为我想知道这是否与 HDD 上的集群有关? 谢谢! 最佳答案
我发现我可以写 SELECT CAST(Min(mynumber) AS VARCHAR(Max))+'mystring' AS X 作为 SELECT CAST(Min(mynumber) AS V
我必须将字符串“johnmelling”值插入到列为 的表中[用户密码] varbinary NOT NULL。 请有人建议我,插入“johnmelling”的最佳转换是什么? 我尝试插入如下, In
我已经在 MSDN 论坛和此处阅读了此内容,但仍然不清楚。我认为这是正确的: Varchar(max) 将存储为文本数据类型,因此有缺点。假设您的字段可靠地少于 8000 个字符。就像我的数据库表中的
我有一个这样描述的表: mysql> describe easy_table; +---------------------+--------------+------+-----+---------
我是一名优秀的程序员,十分优秀!