MySQL查询速度慢 - 可能是索引问题?

Slow MySQL query -- possibly an index issue?

提问人:Andrew G. Johnson 提问时间:1/16/2009 最后编辑:Andrew G. Johnson 更新时间:1/16/2009 访问量:283

问:

所以首先这是我的查询:(注意:我知道 SELECT * 是不好的做法,我只是将其切换以使查询更具可读性)

SELECT pcln_cities.*,COUNT(pcln_hotels.cityid) AS hotelcount
  FROM pcln_cities
  LEFT OUTER JOIN pcln_hotels ON pcln_hotels.cityid=pcln_cities.cityid
  WHERE pcln_cities.state_name='California' GROUP BY pcln_cities.cityid
  ORDER BY hotelcount DESC
  LIMIT 5

所以我知道要解决这样的事情,您需要将 EXPLAIN 添加到查询的开头,但我不是 100% 确定如何阅读结果,所以它们是:

替代文本 http://www.andrew-g-johnson.com/query-results.JPG

一个答案告诉我在 EXPLAIN 结果中寻找什么的答案是加分项

编辑城市表具有以下索引(或者是索引?

  • 城市 ID
  • state_name
  • 我只是在两者中添加了一个,因为我认为它可能会有所帮助(它没有)

酒店表具有以下索引(或者是索引?

  • 城市 ID
MySQL的

评论

0赞 Tomalak 1/16/2009
有关数据类型和索引位置的额外信息会很好。

答:

0赞 Paul Tomblin 1/16/2009 #1

看起来您没有关于 pcln_cities.state_name 或 pcln_cities.cityid 的索引?尝试添加它们。

鉴于您已经更新了您的问题,说您确实拥有这些索引,我只能建议您的数据库目前在加利福尼亚州拥有优势城市,因此查询优化器决定进行表扫描并丢弃非加利福尼亚州的城市比使用索引来挑选加利福尼亚的城市更容易。

3赞 Frederik Gheysels 1/16/2009 #2

嗯,你的查询中有些不太对劲。 您使用聚合函数 (count),但您只是按 id 分组。 通常,应对选择列表中所有不是聚合函数的列进行分组。

恕我直言,正如您现在指定查询的那样,DBMS 永远无法正确确定他应该为那些不是聚合的列显示哪些值......

如果你的查询是这样写的,那会更正确:

select cityname, count(*)
from city inner join hotel on hotel.city_id = city_id
group by cityname
order by count(*) desc

如果对 cityName 没有索引,并且对 cityname 进行筛选,则在该列上放置索引将提高性能。

简而言之:在经常用于筛选或排序的列上添加索引可以提高性能。 (简单地说,你可以把它作为一个“指南”,但每种情况都不同。有时,添加跨多个列的索引会很有帮助。 另外,请记住,如果更新或插入记录,索引也需要更新,因此添加/更新/删除记录会略有性能成本)

另一件可以提高性能的事情是使用内部联接而不是外部联接。我认为没有必要在这里使用外部连接。

评论

0赞 Andrew G. Johnson 1/16/2009
太好了,我稍微修改了一下,现在我们在 <1 秒内返回结果——谢谢!
0赞 mson 1/16/2009 #3

您的查询看起来不错。是否有可能其他东西锁定了您需要的记录?桌子特别大吗?我怀疑数据是问题所在,因为没有那么多酒店......

我在MySQL中遇到了类似的问题。在花了一年多的时间进行调整、修补并认为自己是 SQL 虚拟人之后,我切换到了 SQL Server Express。在 SQL Server Express 中,使用完全相同的数据进行完全相同的查询将快 2-5 个数量级。MySQL似乎在处理中等复杂的查询(5+表)时遇到了特别困难的时期。我认为 MySQL 优化器在 SUN 收购该组织后变得迟钝......

评论

0赞 Andrew G. Johnson 1/16/2009
~8000 行(城市),~42000 行(酒店)
0赞 Andrew G. Johnson 1/16/2009
还应该注意的是,我们最近切换了酒店表(旧的表仍然有 >35000 行),而且这个查询总是快如闪电
0赞 mson 1/17/2009
尝试健全性检查 - 将 2 个表和查询复制到 sql server express 并检查运行时。您拥有的数据量几乎是微不足道的,应该立即返回。