如何加速SELECT CONCAT / GROUP BY查询?

时间:2009-07-31 12:35:21

标签: sql mysql query-optimization

我正在从数据库中选择位置(城市,州)。问题是查询运行得有点慢,我不知道如何加快速度。例如:

SELECT CONCAT_WS(', ', city, state) as location, AVG(latitude), AVG(longitude) 
FROM places
WHERE city='New York' AND state='NY'
GROUP BY location

无论如何都会在该位置上有一个CONCAT,因为我希望数据库返回一个漂亮的连接版本的位置(除非有理由在代码中执行此操作)。例如,“纽约,纽约”。实际上,第三列有时被抛入混合(zipcode)。我正在使用MySQL。

优化此查询的最佳方法是什么?

另外,作为第二个问题,添加“DISTINCT”会以任何方式减慢查询速度吗?例如:

SELECT DISTINCT CONCAT_WS(', ', city, state) as location, AVG(latitude), AVG(longitude) 
FROM places
WHERE city='New York' AND state='NY'
GROUP BY location

(我现在正在这样做,但在提出这个问题的过程中,我意识到由于GROUP BY子句,DISTINCT不是必需的;但是,因为没有必要,我想知道它是否有任何区别如果我为了加快查询速度而烦恼地摇动船只。)

编辑:已经有关于城市,州和邮政编码的索引;加上他们的组合(城市,邮政编码;以及州/邮政编码)。

4 个答案:

答案 0 :(得分:4)

(state, city)上创建一个复合索引,并按以下步骤重写您的查询:

SELECT  CONCAT_WS(', ', city, state) AS location, AVG(latitude), AVG(longitude) 
FROM    places
WHERE   state='NY'
        AND city='New York'
GROUP BY
        state, city

请注意,对于此查询,您可以省略GROUP BY子句:

SELECT  'New York, NY' AS location, AVG(latitude), AVG(longitude) 
FROM    places
WHERE   state='NY'
        AND city='New York'

但是,此查询仍然需要它:

SELECT  CONCAT_WS(', ', city, state) AS location, AVG(latitude), AVG(longitude) 
FROM    places
WHERE   state='NY'
GROUP BY
        state, city

答案 1 :(得分:2)

这很有趣,但人们对数据库的几乎所有问题都是速度,而不是存储要求。那应该告诉你一些事情: - )

我们之前遇到过这样的问题而且我已多次说过这样的问题:每行功能通常不能很好地扩展。我们发现修复它们的最佳方法是插入/更新触发器(我假设MySQL有这些)。

创建另一个列调用pretty_city_state(或其他),并在插入或更新行时让触发器从城市和州填充它。然后在其上创建一个索引。

这利用了这样一个事实,即数据库行通常比写入时更多地(特别是在这种情况下)。通过在写入时评估该列,您可以承担写入(数千)而不是读取(可能是数百万)的成本。当 应该被承担时,这就是写作,因为pretty_city_state只会在城市或州改变时才会改变。如果你对每一个选择都进行连续,你就会浪费精力。

尝试并测量差异 - 我相信你会发现你的选择会以最小的触发成本尖叫(而且一旦你拥有数据库中的所有城市和状态,成本就会完全消失。

是的,我知道这打破了3NF。出于性能原因这样做是完全可以接受的如果你知道你正在做什么

您的查询可以完成:

SELECT pretty_city_state as location, AVG(latitude), AVG(longitude) 
FROM places
WHERE city='New York' AND state='NY'
GROUP BY pretty_city_state
如果你可以在开始查询之前连接城市和州,那么

或者甚至更快(测量,不要猜测):

SELECT pretty_city_state as location, AVG(latitude), AVG(longitude) 
FROM places
WHERE pretty_city_state ='New York, NY'
GROUP BY pretty_city_state

答案 2 :(得分:0)

最佳优化这样的查询的一种方法是将这些列设置为索引列。这样,它可以轻松地根据树或散列进行排序/分组。此外,字符串的连接也可能有一些含义。

答案 3 :(得分:0)

在字段“city”和“state”上添加索引会有所帮助。

此外,根据每个字段的基数(不同值的数量),MySQL的版本,表引擎和其他参数,反转WHERE子句可能会影响查询的执行时间。我试试:

WHERE state='NY' AND city='New York'