[英]MySQL Index on TEXT Column not Effective
I've got a fairly straightforward table for storing key:value pairs, set up like: 我有一个非常简单的表来存储key:value对,设置如下:
CREATE TABLE `assetProperties` (
`propertyKey` varchar(255) NOT NULL,
`propertyValue` text NOT NULL,
`id` bigint(20) NOT NULL,
`assetInstance_id` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
KEY `FK67F768435C68E1C0` (`id`),
KEY `FK67F76843FBDFC83F` (`assetInstance_id`),
KEY `keyIndex` (`propertyKey`),
KEY `valIndex` (`propertyValue`(255)),
CONSTRAINT `FK67F76843FBDFC83F` FOREIGN KEY (`assetInstance_id`) REFERENCES `assets` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
...and there are a reasonable number of entries in this table: ...并且此表中有合理数量的条目:
mysql> select count(*) from assetProperties;
+----------+
| count(*) |
+----------+
| 19931305 |
+----------+
...and what I want to do is find entries that exactly match a given key:value pair. ...而我要做的是找到与给定的key:value对完全匹配的条目。 For example, using a query like: 例如,使用如下查询:
SELECT count(*) FROM assetProperties WHERE propertyKey = "Wood Species"
AND propertyValue = "Jarrah";
Without any indexes on propertyKey
and propertyValue
, that query runs quite slowly, like on the order of 10+ seconds. 在propertyKey
和propertyValue
上没有任何索引,该查询运行速度非常慢,大约需要10秒钟以上。 Which is to be expected. 这是可以预期的。 The problem is, even after adding indexes on both fields, the query time is not improved. 问题是,即使在两个字段上都添加了索引之后,查询时间也没有得到改善。
The strange thing is, the index on propertyKey
appears to be working correctly: 奇怪的是, propertyKey
上的索引似乎正常工作:
-- Before adding index
mysql> SELECT count(*) FROM assetProperties WHERE propertyKey = "Wood Species";
+----------+
| count(*) |
+----------+
| 339395 |
+----------+
1 row in set (9.37 sec) <-- bad
-- After adding index
mysql> SELECT count(*) FROM assetProperties WHERE propertyKey = "Wood Species";
+----------+
| count(*) |
+----------+
| 339395 |
+----------+
1 row in set (0.16 sec) <-- reasonable
...while the index on propertyValue
appears to have made little difference: ...虽然propertyValue
上的索引似乎没有什么区别:
-- Before adding index
mysql> SELECT count(*) FROM assetProperties WHERE propertyValue = "Jarrah";
+----------+
| count(*) |
+----------+
| 219099 |
+----------+
1 row in set (12.51 sec) <-- bad
-- After adding index
mysql> SELECT count(*) FROM assetProperties WHERE propertyValue = "Jarrah";
+----------+
| count(*) |
+----------+
| 219099 |
+----------+
1 row in set (9.75 sec) <-- still garbage
The only difference between propertyKey
and propertyValue
is that the former is a varchar(255)
column and the latter is text
. propertyKey
和propertyValue
之间的唯一区别是,前者是varchar(255)
列,后者是text
。 Is there something preventing MySQL from making efficient use of the index on the text
column, or anything I can do to make the query faster? 是否有某些因素阻止MySQL有效利用text
列上的索引,或者我可以做些什么来加快查询速度?
Edit 编辑
Also tried adding a multi-column index across both fields. 还尝试在两个字段之间添加多列索引。 Made no difference. 没什么区别。
And further, if I add a new column (say propertyValueShort
) of type varchar(255)
and copy the values from propertyValue
into the new column and set up the relevant indexes, it works as it should: 此外,如果我添加类型为varchar(255)
的新列(例如, propertyValueShort
),并将propertyValue
的值复制到新列中并设置相关索引,它将按如下方式工作:
mysql> SELECT count(*) FROM assetProperties WHERE propertyKey = "Wood Species" AND propertyValueShort = "Jarrah";
+----------+
| count(*) |
+----------+
| 219099 |
+----------+
1 row in set (0.14 sec) <-- acceptable
So that may be the immediate answer (the longest propertyValue
currently in use is 88 characters, so I don't really need to be using text
there). 因此,这可能是直接的答案(当前使用的最长的propertyValue
是88个字符,因此我真的不需要在那里使用text
)。 However still doesn't explain why the index on the text
column performs so poorly. 但是仍然无法解释为什么 text
列上的索引表现如此差。
PRIMARY KEY (`id`),
KEY `keyIndex` (`propertyKey`),
--> - >
PRIMARY KEY(property_key, id),
INDEX(id),
Why? 为什么?
property_key
will now be "next to each other", thereby minimizing disk reads. 这意味着具有相同property_key
所有行现在将“彼此相邻”,从而最大程度地减少了磁盘读取。 id
an AUTO_INCREMENT
? id
是AUTO_INCREMENT
吗? If so, INDEX(id)
is sufficient; 如果是这样,则INDEX(id)
就足够了; PK is not needed. 不需要PK。 Else... Why have id
? 其他...为什么要有id
? Can you get rid of it? 你能摆脱它吗? Not really; 并不是的; you still need to make the PK unique somehow. 您仍然需要使PK与众不同。 What is the ROW_FORMAT
of the table? 该表的ROW_FORMAT
是什么? How long is property_value
typically? 通常, property_value
多长时间? Those impact whether 'big' fields such as TEXT are kept with the row, or stored separately. 这些都会影响“大”字段(例如TEXT)是随行保留还是单独存储。
(Bottom line: key-value schemas suck.) (底线:键值模式很糟糕。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.