1

我正在与一个非常简单的表上的一些性能问题作斗争,当使用它的主键(bigint)获取数据时似乎很慢

我有这张表有 1.24 亿个条目:

CREATE TABLE `nodes` (
  `id` bigint(20) NOT NULL,
  `lat` float(13,7) NOT NULL,
  `lon` float(13,7) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `lat_index` (`lat`),
  KEY `lon_index` (`lon`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

和一个简单的查询,它使用 IN 子句从另一个表中获取一些 id 以从节点表中获取数据,但是从该表中获取几行只需要 1 小时。EXPLAIN 向我展示了它没有使用 PRIMARY 键作为索引,它只是扫描整个表。为什么?id 和另一个表中的 id 列都来自 bigint(20) 类型。

mysql> EXPLAIN SELECT lat, lon FROM nodes WHERE id IN (SELECT node_id FROM ways_elements WHERE way_id = '4962890');
+----+--------------------+-------------------+------+---------------+--------+---------+-------+-----------+-------------+
| id | select_type        | table             | type | possible_keys | key    | key_len | ref   | rows      | Extra       |
+----+--------------------+-------------------+------+---------------+--------+---------+-------+-----------+-------------+
|  1 | PRIMARY            | nodes             | ALL  | NULL          | NULL   | NULL    | NULL  | 124035228 | Using where | 
|  2 | DEPENDENT SUBQUERY | ways_elements     | ref  | way_id        | way_id | 8       | const |         2 | Using where | 
+----+--------------------+-------------------+------+---------------+--------+---------+-------+-----------+-------------+

该查询SELECT node_id FROM ways_elements WHERE way_id = '4962890'只返回两个节点 id,因此整个查询应该只返回两行,但它或多或少需要 1 小时。

使用“强制索引(PRIMARY)”没有帮助,即使它会有所帮助,为什么 MySQL 不采用该索引,因为它是主键?EXPLAIN 甚至没有在 possible_keys 列中提及任何内容,但 select_type 显示 PRIMARY。

难道我做错了什么?

4

2 回答 2

1

这表现如何?

SELECT lat, lon FROM nodes t1 join ways_elements t2 on (t1.id=t2.node_id) WHERE t2.way_id = '4962890'

我怀疑您的查询是针对“IN”子句中的每个项目检查节点中的每一行。

于 2013-04-15T09:47:00.723 回答
1

这就是所谓的相关子查询。您可以将此作为参考或在 Stackoverflow 上发布的这个热门问题。一个更好的查询是:

SELECT lat,
       lon
FROM nodes n
JOIN ways_elements w ON n.id = w.node_id
WHERE way_id = '4962890'
于 2013-04-15T10:23:48.187 回答