如何索引 - 优化这个 MySQL 查询?

Posted

技术标签:

【中文标题】如何索引 - 优化这个 MySQL 查询?【英文标题】:How can I index - optimize this MySQL query? 【发布时间】:2017-03-15 15:52:09 【问题描述】:

我有一个这样的查询:

SELECT id, terrain, occupied, c_type 
FROM map 
WHERE x >= $x-$radius 
  AND x <= $x+$radius 
  AND y >= $y-$radius 
  AND y <= $y+$radius 
   ORDER BY 
     x ASC, 
     y ASC

我的桌子是这样的:

CREATE TABLE `map` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `occupied` tinyint(2) NOT NULL DEFAULT '0',
  `c_type` tinyint(4) NOT NULL DEFAULT '0',
  `x` int(11) NOT NULL,
  `y` int(11) NOT NULL,
  `terrain` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8mb4_general_ci

我删除了除 PRIMARY KEY 之外的所有索引,因为我不确定索引如何与 SQL 一起使用。 我可以做些什么来调整这个查询?谢谢...

这不是重复的,检查 cmets!

【问题讨论】:

见***.com/questions/3567981/how-do-mysql-indexes-work How do MySQL indexes work?的可能重复 当您使用 WHERE 语句数据库按您指定的字段搜索数据时。所以你可以在'x'和'y'中添加索引。 。 @AlexSlipknot 如果我想完全避免表扫描,您能否展示一下索引的外观?比如,我应该按什么顺序放置 x、y、id、占用列等,以便优化器有效地使用它? @MetalCastles - INDEX(x,y,id) -- id 没有添加任何有用的东西。拥有所有列(因此“覆盖”)可能是好的。然而,正如 SolarBear 指出的那样,“批量可能会减慢速度”。 【参考方案1】:

查询可以做到的最好的事情是

INDEX(x, y)  -- In this order

这将是有效的

WHERE x >= $x-$radius 
  AND x <= $x+$radius 

但不适用于过滤y

它会(可能)避免ORDER BY x ASC, y ASC 的“文件排序”。请注意,索引顺序必须与此顺序匹配。

为任何尝试的SELECT 提供EXPLAIN SELECT ...

并且,请在 MyISAM 被移除之前切换到 InnoDB。

Here 是一本关于 MySQL 索引的快速指南。

【讨论】:

我创建了索引gmp (x, y, id, terrain, occupied, c_type),并在上面的查询中运行 EXPLAIN 显示 id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE map range gmp gmp 8 NULL 1955 Using where;使用索引【参考方案2】:

所以,我添加了索引 gmp 与列 x, y, id, terrain, occupied, c_type 和 EXPLAIN SELECT 显示:

id: 1

select_type: SIMPLE

table: map

type: range

possible_keys: gmp

key: gmp

key_len: 8

ref: NULL

rows: 1955

Extra: Using where; Using index

所以,我想它现在可以工作了。

【讨论】:

以上是关于如何索引 - 优化这个 MySQL 查询?的主要内容,如果未能解决你的问题,请参考以下文章

mysql性能优化-慢查询分析,优化索引最佳实践

如何优化这个 MySQL 查询

如何优化这个 MySql 查询 - 连接 3 个表?

如何为MySQL查询优化选择最佳索引

mysql中如何根据经纬度优化这个距离查询

优化 MySQL 连接查询以删除 Using temporary 并使用索引?