我有一个相当简单的表来存储键:值对,设置如下:
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
...此表中有合理数量的条目:
mysql> select count(*) from assetProperties;
+----------+
| count(*) |
+----------+
| 19931305 |
+----------+
...我想要做的是找到与给定键完全匹配的条目:值对。例如,使用如下查询:
SELECT count(*) FROM assetProperties WHERE propertyKey = "Wood Species"
AND propertyValue = "Jarrah";
propertyKey
和propertyValue
上没有任何索引,该查询运行速度非常慢,就像大约10秒以上一样。这是可以预料的。问题是,即使在两个字段上添加索引之后,查询时间也没有得到改善。
奇怪的是,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
... 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
propertyKey
和propertyValue
之间的唯一区别是前者是varchar(255)
列,后者是text
。有没有什么东西阻止MySQL有效利用text
列上的索引,或者我可以采取哪些措施来加快查询速度?
修改
还尝试在两个字段中添加多列索引。没有区别。
此外,如果我添加类型为propertyValueShort
的新列(例如varchar(255)
)并将propertyValue
中的值复制到新列中并设置相关索引,则可以应该:
mysql> SELECT count(*) FROM assetProperties WHERE propertyKey = "Wood Species" AND propertyValueShort = "Jarrah";
+----------+
| count(*) |
+----------+
| 219099 |
+----------+
1 row in set (0.14 sec) <-- acceptable
因此,这可能是直接答案(当前使用的最长propertyValue
是88个字符,所以
text
列上的索引表现不佳。
答案 0 :(得分:0)
PRIMARY KEY (`id`),
KEY `keyIndex` (`propertyKey`),
- &GT;
PRIMARY KEY(property_key, id),
INDEX(id),
为什么?
property_key
的所有行现在将“彼此相邻”,从而最大限度地减少磁盘读取。id
是AUTO_INCREMENT
吗?如果是这样,INDEX(id)
就足够了;不需要PK。否则......为什么要id
?你能摆脱它吗?并不是的;你还需要以某种方式使PK独一无二。桌子的ROW_FORMAT
是多少? property_value
通常需要多长时间?这些影响是否像TEXT这样的“大”字段与行保持在一起,还是单独存储。
(底线:键值模式很糟糕。)