分解JOIN查询
许多高性能的网站都分解了JOIN查询。你可以用查询多张单独的表的方法来替代多表JOIN查询,并且之后在应用程序执行这个JOIN.举个例子,
mysql> SELECT * FROM tag
-> JOIN tag_post ON tag_post.tag_id=tag.id
-> JOIN post ON tag_post.post_id=post.id
-> WHERE tag.tag='mysql'
你可以使用如下语句替换
mysql> SELECT * FROM tag WHERE tag='mysql';
mysql> SELECT * FROM tag_post WHERE tag_id=1234;
mysql> SELECT * FROM post WHERE post.id in (123,456,567,9098,8904);
初次看上去的确很不错。这是因为查询语句多了,但是并没有返回结果。然而,这种结构能带来明显的性能提升:
- 缓存是高效的。许多应用都缓存了直接和表映射的“对象”。在这个例子中,如果"tag mysql"对象被缓存了,上面的第一步查询就可以省略了。如果你发现post的id为123,567或9098在缓存中,你就可以把它们从in语句中除去。这种策略也可以给查询缓存带来好处。如果仅仅只有一张表常常的改变。分解JOIN也可以降低缓存的无效次数。
- 对于MyISAM表,在每张表执行一个查询语句,使用表锁要更有效率:这个查询语句将会单独的锁定表并且比锁定它们很长时间的形式相对容易一些。
- 在应用程序中使用JOIN的方法,比较有利于数据库的伸缩。因为可能会把表放到不同的数据库服务器上。
- 查询自身是更有效率的。一个例子,使用IN替代一个JOIN会让MySQL排序行的ID和获取行要更好一些。以后我们会详细解释。
- 会降低冗余行的读取。在应用中做JOIN意味着,你获取行仅仅需要一次。然而,一个在非范式的查询会重复访问相同的数据。由于此,这种结构也可以减少网络流量以及内存的使用。
- 在一定程度上,你可以发现这项技术都是使用了hash join,而不是使用MySQL内置循环策略去执行一个JOIN.一个hash join会更高效。在这章的join策略中会详细说到。
小结:应用中的JOIN更有效的时候。
- 你从先前查询的结果中缓存和重用了很多数据。
- 大部分表都为MyISAM。
- 数据是分布式的,这些数据很多都是在不同的数据库服务器上。
- 在大表中,用IN()替代了JOIN.
- 一个JOIN多次使用了相同的表。