删除此JOIN可以获得性能提升吗?

时间:2010-04-08 03:29:18

标签: mysql join

我有一个包含100万行的“items”表和一个包含20,000行的“users”表。当我从“items”表中选择时,我在“users”表(items.user_id = user.id)上进行连接,这样我就可以从users表中获取“用户名”。

我正在考虑在items表中添加用户名列并删除联接。我可以期待从中获得不错的性能提升吗?它已经很快了,但减少我的负载(这是非常高的)会很好。

缺点是,如果用户更改了用户名,项目仍然会反映他们的旧用户名,但如果我能期望性能提升,那么这对我来说没问题。

我问的是stackoverflow,因为基准并没有告诉我太多。两个查询都很快完成。无论如何,我想知道删除连接是否会在很大程度上减轻数据库的负担。

带连接的示例查询:
选择ItemidItemsubmitter_idItemsource_imageItemcached_image,{ {1}}。Itemsource_titleItemsource_urlItemwidthItem,{{1 } {。{}},heightItemstatusItempopularItemmade_popularItemfave_countItemtagsItemuser_artItemnudity。{ {1}},ItemcreatedItemmodifiedItemremovedItem。{{1 },nofrontItemtestItemrecsItemrecs_dataUseridUserusernameUserpasswordUseremailUser,{ {1}}。fullnameUserprofileurlUserhomepageUserbio,{{1 } {。{}},UserlocationUseravatarUserff_userUserff_keyUserff_last_faveidUsertwitter_userUsertwitter_passUser。{ {1}},emailalertsUsershowunsafeUserviewUserfb_uid。{{1 },Userfb_sessionUserfb_avatarUsertwitter_uid FROM User AS twitter_data LEFT JOIN User AS twitter_autopost ON(Useruri = Usercreated)WHERE User。{{1} }!= 1 AND modifieditems!= 1 AND Itemusers不是NULL和裸露!= 1 ORDER BY User。{{1 DESC LIMIT 1040,290;

没有加入的示例查询:
选择Itemsubmitter_idUseridItemnofrontItemremoved,{ {1}}。Itemmade_popularItemmade_popularItemidItem,{{1 } {。{}},submitter_idItemsource_imageItemcached_imageItemsource_titleItemsource_urlItemwidthItemheightItemstatus。{ {1}},ItempopularItemmade_popularItemfave_countItem。{{1 },tagsItem FROM user_art AS Item WHERE nudityItem!= 1 AND created。{{ 1}}!= 1 AND Itemmodified不是NULL和nudity!= 1 ORDER BY Itemremoved DESC LIMIT 1040,290;

5 个答案:

答案 0 :(得分:5)

正确的答案是在目标环境中测量它,看看它是否有所作为。然后进行成本/收益分析,看看它是否值得。

成本是增加的存储空间和可能数据不同步(但请参阅下文有关如何缓解此问题)。好处是速度提高或负载减少。

数据库模式设置 - 忘记操作,它们应该随着基础数据的变化而定期调整。这就是DBA的代价,持续监控和调整。

在任何情况下,通过使用触发器,可以在相当容易的DBMS中轻松控制列的复制。我的意思是在用户表上放置一个插入/更新触发器,这样,如果用户更改了用户名,它也会在items表中更改(反之亦然)。

MySQL是否符合我对DBMS的定义,我无法评论 - 我自己就是DB2。但是,从第三范式中恢复是一种久经考验的技术,用于将数据库中的每一个最后一次性能绞尽脑汁,并且只要您了解后果,就可以接受。很少有人抱怨他们的数据库占用了太多的磁盘空间。 许多抱怨他们的查询运行速度有多慢。

请记住,在您遇到性能问题时,如果 ,则需要进行还原。这不应该只是因为你认为它可以减少负荷。除非负载(或所花费的时间)实际上是一个问题,否则成本/收益分析的收益部分为零,因此任何sane bean计数器都会告诉您这意味着“没有变化”。


根据您添加的查询,我有几点要做:

  • 首先是nudity列。请告诉我如何访问这个数据库: - )
  • 您应提取所需的列。如果用户名是User表中的所有要求,则不应该在第一个查询中获得所有额外的内容。可能同样适用于Item的东西 - 只能得到你需要的东西。
  • 确保在WHERE子句中使用的所有列上都有索引 - 这可能还需要组合索引(具有多个列的索引)。索引的内容取决于您的查询,但WHERE子句中使用的每个列都是分析的良好开端。
  • 对于大型表格,您可以考虑将已删除的项目定期“扫描”到单独的表格中(例如RemovedItems),以最小化Items的大小并加快查询速度。但请记住,这只有在您很少需要查找romoved项目时才有用,因为它会使这些查询复杂化(通过强制它们在两个表而不是一个表中搜索)。同样,这是一个成本/收益的事情。一百万行并不是那么大的表(至少在我的世界里)。

答案 1 :(得分:1)

我建议您保持这种方式来保留规范化的表格。我认为将用户名放在项目表上不是一个好主意,因为它会使数据变得多余。您是否尝试过重新编制表格索引?

答案 2 :(得分:0)

如果您错过了items.user_iduser.id上的索引,或者您使用的是糟糕的数据库,那么您只会看到显着的性能提升。否则,性能不会显着提高。

答案 3 :(得分:0)

JOINS总是占用比简单SELECT语句更多的资源。所以是的,删除JOIN应该会提高性能。

答案 4 :(得分:0)

  

我有一个包含100万行的“items”表和一个包含20,000行的“users”表。

也就是说,无论您是JOIN还是非规范化,您仍然通过网络传输大约1M / 20k = 50倍User信息而非严格必要。对数据进行编码,传输和解码会增加负载。

  

我正在考虑在items表中添加用户名列并删除联接。

为什么你原来的JOIN还会带来所有其他(可能是浩繁的)信息(例如User.profileurlUser.homepage等),如果你需要的只是用户名?请记住,对于User列,您平均每个位信息传输50份。您是否考虑过彻底删除SELECT JOIN中的列UserItem以及OFFSET ... LIMIT ...表?)

  

我问的是stackoverflow,因为基准并没有告诉我太多。两个查询都很快完成。无论如何,我想知道删除连接是否会在很大程度上减轻数据库的负担。

在第一阶段,删除不打算使用的列可以减少负载,因为必须编码,传输(从服务器到客户端应用程序)的数据越少,然后解码。

在第二阶段,让我先谈谈我自己的问题:你真的需要一次拍摄所有百万行吗?如果不这样做,例如如果您是用户界面驱动的并且您对它们进行了分页(使用User),那么您不一定会关心50x LIMIT信息重复(除非SELECT进入成千上万。)否则,您可能希望衡量 消除50倍重复的优势,只需先User.id {{1} }和User.username进入应用程序内存(20k对,进入哈希表/映射),然后SELECT只用 Item行(1M次迭代)每次解析,在应用程序级别,Item.user_id对着哈希表/映射。

当然,总是使用EXPLAIN来确保在使用索引时存在并使用正确的索引,并在任何表从几百行以下增长后运行ANALYZE TABLE成千上万。