MYSQL 搜索条件的细微差别会产生巨大的差异,我无法理解它

Posted

技术标签:

【中文标题】MYSQL 搜索条件的细微差别会产生巨大的差异,我无法理解它【英文标题】:Slight difference in MYSQL search condition makes huge difference, can't wrap my mind around it 【发布时间】:2018-01-15 10:56:46 【问题描述】:

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

我有一个大约 100 万行的用户个人资料表。我想过滤值并只取回我感兴趣的内容。

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

为了过滤它的“距离”方面,我创建了一个具有纬度范围经度范围的任意矩形。

除了“距离”属性之外,我还有一些我也会过滤的通用属性:比如年龄、性别等。

我索引了包括纬度和经度在内的所有字段。顺便说一句,我使用 FLOAT 类型来表示经纬度。

所以,这是一个简单的 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 之间的过滤器值(以及其他属性)进行测试时,查询运行相对较快(49 毫秒)。但是,当我将经度值更改为 -105 和 -103.5(0.1 差异!)之间时,查询需要 493 毫秒。 (10次!?!?!?!)

由此产生的选择结果差异只有几百(可以理解)。


所以我也尝试更改其他值,看看到底是什么原因造成的。我改变了纬度值。纬度值似乎对性能没有任何影响。卧槽!

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

仍然没有线索。

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

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;


【问题讨论】:

取决于许多因素 .. 所以你应该更新你的问题 .. 添加你的查询,你的表架构和一个合理的数据样本 我添加了一些附加信息,如果需要其他信息,请告诉我。 您可以通过查看查询计划来检查 MySQL 正在做什么,两种情况都运行 EXPLAIN <query> 看来我可能已经找到了我的问题,当它是-103.5时,行数大约是500,000,而当它是-103.6时,它大约是77000。这似乎是造成的问题。并且 Extra 字段也有区别...谢谢。让我深入研究一下。 Afaik 索引的顺序无关紧要。可能发生的是索引统计信息已更新。您应该在gender 上删除索引,它唯一做的就是生成愚蠢的执行计划。只有少数可能值和均匀分布的索引只会产生问题。 【参考方案1】:

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

查询中的微小变化(在我的例子中)导致优化器提出完全不同的执行计划,因此其中一个值的微小变化导致结果的巨大差异。

我修复它的方法是更改​​表的结构(索引等),以便 MySQL 在制定执行计划时有更好的想法。就我而言,修复索引就可以了。我添加了多列索引以在一定程度上迫使优化器走某条路线。

就到这里了,感谢各位网友的帮助。

【讨论】:

以上是关于MYSQL 搜索条件的细微差别会产生巨大的差异,我无法理解它的主要内容,如果未能解决你的问题,请参考以下文章

18 | 为什么这些SQL语句逻辑相同,性能却差异巨大?

18 | 为什么这些SQL语句逻辑相同,性能却差异巨大?

JavaScript 和 Lua 之间的细微差别 [关闭]

Vigenere Cipher - 莫名其妙的细微差别

查询速度的巨大差异

最全解释Mysql 的join中on与where 过滤条件差异