1

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

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

无论如何,该位置都会有一个 CONCAT,因为我希望数据库返回一个漂亮的连接版本的位置(除非有理由在代码中这样做)。例如,“纽约,纽约”。实际上,有时会添加第三列(邮政编码)。我在 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

4 回答 4

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
于 2009-07-31T12:40:27.457 回答
2

这很有趣,但人们对数据库的几乎所有问题都是速度,而不是存储要求。你能从中了解到点东西 :-)

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

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

这利用了这样一个事实,即读取数据库行的频率通常高于写入频率(尤其是在这种情况下)。通过在写入时评估该列,您可以承担写入(数千)而不是读取(可能是数百万)的成本。它是应该承担的写作,因为 pretty_city_state 只会在城市或州发生变化时发生变化。如果您在每次选择时都执行 concat,那么您就是在浪费精力。

尝试一下并衡量差异 - 我相信您会发现您的选择会以最低的触发器成本尖叫(一旦您的数据库中包含所有城市和州,该成本就会完全消失。

是的,我知道这会破坏 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
于 2009-07-31T12:53:26.080 回答
0

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

于 2009-07-31T12:37:56.130 回答
0

在“城市”和“州”字段上添加索引会有所帮助。

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

WHERE state='NY' AND city='New York'
于 2009-07-31T12:43:30.453 回答