MYSQL搜索条件的微小差异会产生巨大的差异,无法围绕它进行思考

时间:2018-01-15 10:56:46

标签: mysql geolocation

我无法说我是MySQL的专家,更多的是在新手方面。但我知道一些基本的性能成本概念。话虽如此,

我有一个约100万行的用户配置文件表。我想过滤价值观,只回到我感兴趣的地方。

在列中,我有纬度和经度列。

为了过滤"距离"方面,我创建了一个任意矩形,其中纬度范围经度范围

随着"距离"属性,我也有一些我也过滤的通用属性:如年龄,性别等。

我索引了所有字段,包括纬度和经度。我使用FLOAT类型用于lat和long,BTW。

因此,它是一个简单的SELECT查询,具有多个属性,如此,

SELECT user_id FROM profiles WHERE gender = 1 AND birthday BETWEEN '1980-01-27' AND '1988-01-27' AND longitude BETWEEN -105 AND -103.6 AND latitude BETWEEN 35 AND 40

************这是最奇怪的事情**************

当我使用经度的滤波器值(例如-105和-103.6)(以及其他属性)进行测试时,查询运行相对较快(49ms)。但是当我将经度值更改为-105到-103.5(0.1差异!)时,查询需要493ms。 (10次!?!?!?!)

结果选择结果差异只有几百(理解情况如此)。

所以我也尝试更改其他值,看看是什么造成了这个。我改变了纬度值。纬度值似乎对性能没有任何影响。 WTF!

我尽可能删除索引,并尝试使用不同的索引变体来解决问题。

仍然没有线索。

所以,我深入研究了这一点,我将经度值更改为-105到-103.597之间。 -103.597需要49ms,而-105和-103.596需要526ms。

0.001差异不可能在查询性能上产生那种差异。 我错过了什么?

我使用InnoDB,mysql版本5.7.19,顺便说一句。

表架构,

CREATE TABLE `profiles` (
  `user_id` varchar(8) NOT NULL DEFAULT '',
  `gender` tinyint(1) NOT NULL DEFAULT '0',
  `orientation` tinyint(1) NOT NULL DEFAULT '0',
  `birthday` date NOT NULL DEFAULT '2000-01-01',
  `height` tinyint(2) NOT NULL DEFAULT '0',
  `ethnicity` int(2) NOT NULL DEFAULT '0',
  `latitude` float NOT NULL DEFAULT '0',
  `longitude` float NOT NULL DEFAULT '0',
  PRIMARY KEY (`user_id`),
  KEY `gender` (`gender`),
  KEY `birthday` (`birthday`),
  KEY `longitude` (`longitude`),
  KEY `latitude` (`latitude`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

enter image description here

enter image description here

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:0)

MySQL运行内部优化器来确定所有查询的执行计划。

查询中的细微变化(在我的情况下)导致优化器提出了完全不同的执行计划,因此其中一个值稍有变化的结果差别很大。

我修复它的方法是改变表的结构,(索引等),以便MySQL在提出执行计划时有更好的想法。就我而言,修复索引就可以了。我添加了多列索引来强制优化器走一条路。

据我所知,感谢所有评论者的帮助。