我无法说我是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;
答案 0 :(得分:0)
MySQL运行内部优化器来确定所有查询的执行计划。
查询中的细微变化(在我的情况下)导致优化器提出了完全不同的执行计划,因此其中一个值稍有变化的结果差别很大。
我修复它的方法是改变表的结构,(索引等),以便MySQL在提出执行计划时有更好的想法。就我而言,修复索引就可以了。我添加了多列索引来强制优化器走一条路。
据我所知,感谢所有评论者的帮助。