TEXT列上的MySQL索引无效

时间:2015-12-03 07:14:02

标签: mysql indexing query-optimization entity-attribute-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

...此表中有合理数量的条目:

mysql> select count(*) from assetProperties;
+----------+
| count(*) |
+----------+
| 19931305 |
+----------+

...我想要做的是找到与给定键完全匹配的条目:值对。例如,使用如下查询:

SELECT count(*) FROM assetProperties WHERE propertyKey = "Wood Species" 
    AND propertyValue = "Jarrah";

propertyKeypropertyValue上没有任何索引,该查询运行速度非常慢,就像大约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

propertyKeypropertyValue之间的唯一区别是前者是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列上的索引表现不佳。

1 个答案:

答案 0 :(得分:0)

PRIMARY KEY (`id`),
KEY `keyIndex` (`propertyKey`),

- &GT;

PRIMARY KEY(property_key, id),
INDEX(id),

为什么?

  • InnoDB使用数据“聚类”PK。这意味着具有相同property_key的所有行现在将“彼此相邻”,从而最大限度地减少磁盘读取。
  • idAUTO_INCREMENT吗?如果是这样,INDEX(id)就足够了;不需要PK。否则......为什么要id?你能摆脱它吗?并不是的;你还需要以某种方式使PK独一无二。

桌子的ROW_FORMAT是多少? property_value通常需要多长时间?这些影响是否像TEXT这样的“大”字段与行保持在一起,还是单独存储。

(底线:键值模式很糟糕。)