2009-07-24 96 views
1

我该如何改进这个查询? 请点击这里告诉我,我所有的选项,我的社交网络DB只挺大随着我的mysql数据库增长,我有什么选择

这个查询花费2.1231秒

SELECT friend_friend.friendid, friend_reg_user.disp_name, friend_reg_user.pic_url, friend_reg_user.online 
FROM friend_friend 
INNER JOIN friend_reg_user ON friend_friend.friendid = friend_reg_user.auto_id 
WHERE userid =1 
AND friend_friend.status =1 
ORDER BY autoid DESC 
LIMIT 59535 , 15 


##################################################################################################################################### 
# id # select_type # table   # type # possible_keys # key  # key_len # ref      # rows # Extra  # 
##################################################################################################################################### 
# 1 # SIMPLE  # friend_friend # ref  # userid  # userid # 5  # const     # 59843 # Using where# 
# 1 # SIMPLE  # friend_reg_user # eq_ref # PRIMARY  # PRIMARY # 4  # friend_friend.friendid # 1  #   # 
##################################################################################################################################### 

我有哪些选项时,此表是说一百万,或甚至2万行大?此表是用来确定谁是用户的朋友

回答

2

我知道一个程序员是谁在他的数据库工作了800万点的记录,它确实没有改变速度那么多。这只是创建正确的索引并确保您以有效的方式获取数据。 (关系的数字ID非常有用)

此外,您的查询在大多数情况下确实是准系统。没什么太花哨。这可能只是您的服务器延迟。

+0

是的,我认为它已尽可能优化,所有正确的索引和东西,但超过2秒是缓慢的。这是从本地运行的,也许这可能是为什么它很慢? – JasonDavis 2009-07-24 11:45:35

+0

800万条记录并不是那么多......试着看看当你达到10亿时会发生什么。 – MarkR 2009-07-26 21:43:16

+0

我可以证明,拥有超过1亿5千万行myisam表的quieries在处理可以高效使用索引的查询时仍然很快。 – nos 2009-07-26 21:46:18

2

也许我真的不明白你的方案,但你真的需要一个LEFT JOIN?你能不能使用INNER JOIN

(我常常听到它可能是更好的性能,因为它返回少行;你的情况,如果你想一个人的朋友,我没有看到左侧的点连接:朋友会“链接”,和,因此,必须在“链接”表中的条目,否)

此外,请确保您有使用上的字段索引:

    在条件
  • (无论是“里”或“加入”);在这里似乎还可以
  • 用于排序; autoid是否有索引?

MySQL在某些应用程序中与真正的大表一起使用,并且如果索引/配置正常,可以非常快地回答;所以,有一些我们应该能够做到的事情;-)

作为一个旁注:你前缀几乎所有字段的名称的表名称(因为字段的名称中的重复,我想) ;你为什么不总是做到这一点?它将使查询只是有点更容易理解;-)

+0

嗨,实际上时间贴2.1231秒是一个内部JOIN我忘了更新它在这里左边加入时间大约是2.4231,所以有一个小小的改进。是的,在所有thye右列上都有索引,并且排序后的autoid是主键,因此它不能有索引权限?我的意思是主键是一个索引? 我想我已经优化了它的最佳效果,但是整整两秒很慢我认为=( – JasonDavis 2009-07-24 11:44:11

+0

ergh,太糟糕了,如果有所有必要的索引:-((并且是的,PK也是一个索引)。步骤将是反规范化(http://en.wikipedia.org/wiki/Denormalization)或Sharding(http://en.wikipedia.org/wiki/Sharding)...但有点让事情变得更难... – 2009-07-24 18:20:13

1

只要列在WHERE子句中的索引,你应该没问题。我会生成一套大量的测试数据并运行一些基准测试。

而且,更重要的是,你自己熟悉MySQL's EXPLAIN语法。它将帮助您确定查询中实际使用了多少行(以及其他内容),并且它是优化查询和表索引的好工具。

0

你应该找出是什么导致它变慢。

您的数据库是否适合内存?如果没有,得到更多 - 不,真的。不管你怎么看,光盘都很慢。

如果查询绝对必须使用光盘(比如你的数据库仅仅是如此庞大的合理的内存,100G +说),那么你应该试图尽量减少它需要IO操作的数量。

实际上这意味着一定量的非规范化(你真的需要一个连接吗?你是否不能在外部参照表上存储(复制)所有必要的域?),并明智地使用覆盖索引。

在InnoDB中(我假设你在这里使用Innodb),主键是集群的。这意味着使用主键的查询比其他索引执行更少的IO(因为索引与数据一起存储在相同的页面中),因为它们不需要为每一行做一个潜在的单独的IO,而这往往是需要在二级索引上。

的基本原理是:

  1. 使用在非生产环境中生产规格硬件数据的生产水平
  2. 诊断什么重现问题导致它
  3. 做一个改变,这您认为可能会修复它
  4. 再次测量,使用相同的生产规格非生产环境来验证修补程序的性能。
  5. 重复,直到你有足够的性能来解决问题(安抚你的客户等)

,如果成功,然后你可以做任何你的正常的检查程序(如回归测试等)将发布改变。

在某些情况下,更改将需要进行重大数据迁移,因此会令人头疼(例如需要更改10Tb数据表的架构)。

相关问题