优化 MySQL - WHERE 和 ORDER BY 使用不同的列

Posted

技术标签:

【中文标题】优化 MySQL - WHERE 和 ORDER BY 使用不同的列【英文标题】:Optomizing MySQL - WHERE and ORDER BY use different columns 【发布时间】:2011-11-17 19:18:59 【问题描述】:

我有一个 115MByte、1,600,000 行的表,用于存储房价和坐标。 “SELECT”查询花费的时间太长。我想知道是否有人可以提出一种加快速度的方法。

我的表的略微简化版本....

CREATE TABLE `prices1` (
    `price` INT(10) NOT NULL,
    `address` VARCHAR(127) NOT NULL,
    `lat` FLOAT(6,4) NOT NULL COMMENT 'GPS latitude',
    `lng` FLOAT(6,4) NOT NULL COMMENT 'GPS longitude',
    INDEX `lat` (`lat`),
    INDEX `price` (`price`)
) ENGINE=MyISAM ROW_FORMAT=DEFAULT

此查询提取 2 英里 x 2 平方英里区域内的记录 ....

SELECT * FROM prices1
WHERE lat >= 55.9430 AND lat <= 55.9641
AND lng >= -3.2279 AND lng <= -3.1901                 
AND price >= 100000 and price <= 400000
ORDER BY price asc
LIMIT 50

... 需要 0.8 秒。 EXPLAIN 说它正在使用索引“价格”。

如果我使用 force index(lat),查询会在 0.1 秒内运行 - 快得多,但我真的希望它更快。

查询将通过具有多个用户的网站运行。所有查询都是相似的,但 lat、lng 和 price 的范围不同。表写入速度并不重要。

谁能建议我如何加快查询速度?或者至少鼓励 mysql 在更好的选择时使用索引 'lat'(我宁愿不使用 'force lat',因为我发现使用 'price' 索引更好地运行从更大区域提取的查询)。

我已经运行了“分析”和“优化”。

我已经阅读了 MySQL 'order by indexation' - 其中相同的索引可用于 'WHERE' 和 'ORDER BY' 子句,但我认为这不能用于 WHERE 是一个范围的地方?

是否值得追求“空间索引”?

欢迎任何想法,因为我真的需要更快地获得这个。

【问题讨论】:

【参考方案1】:

如果你这样做会发生什么:

INSERT INTO temporal
SELECT * FROM prices1
WHERE lat >= 55.9430 AND lat <= 55.9641
AND lng >= -3.2279 AND lng <= -3.1901                 
AND price >= 100000 and price <= 400000



SELECT * from temporal
ORDER BY price asc
LIMIT 50

【讨论】:

感谢@Francisco Soto。运行时间 = 0.11s + 0.001s。我还尝试将“WHERE 价格”部分移到第二个查询中 - 得到了相同的结果。我想知道是否有任何方法可以加快第一次查询的速度 - 我将尝试进一步拆分。 还有,为什么纬度有索引,经度没有索引? 因为它一次只能使用一个索引,并且纬度和经度应该是相当对称的数据,我想我会通过不给它选择来决定更容易使用哪个索引.尝试过 INDEX(lat,lng) 但似乎没有加快速度。 按照您的想法,我还尝试了选择中的子选择(在纬度/经度上选择内部,在价格上进行外部选择)。获得相同的速度。它也存在与使用“force index(lat)”相同的问题,因为使用更大的区域进行不同的搜索会产生非常差的结果。

以上是关于优化 MySQL - WHERE 和 ORDER BY 使用不同的列的主要内容,如果未能解决你的问题,请参考以下文章

MySQL优化:order by和limit

使用 JOIN 优化 SQL 查询的 ORDER BY 和 WHERE

Mysql之order by|group by 排序优化

Mysql group by,order by,dinstict优化

MySQL 不使用带有 JOIN、WHERE 和 ORDER 的索引

为 where 子句和 order_by 创建 MYSQL 索引