select SQL_CALC_FOUND_ROWS DISTINCT media.*, username
from album as album, album_permission as permission, user as user, media as media , word_tag as word_tag, tag as tag
where ((media.album_id = album.album_id and album.private = 'yes' and album.album_id = permission.album_id and (permission.email = '' or permission.user_id = '') ) or (media.album_id = album.album_id and album.private = 'no' ) or media.album_id = '0' )
and media.status = '1'
and media.user_id = user.user_id
and word_tag.media_id = media.media_id
and word_tag.tag_id = tag.tag_id
and tag.name in ('justin','bieber','malfunction','katherine','heigl','wardrobe','cinetube') and media.media_type = 'video'
and media.media_id not in ('YHL6a5z8MV4')
group by media.media_id
order by RAND()
#there is limit too, by 20 rows..
我不知道从哪里开始解释这个查询,但请原谅我并问我是否有任何问题。以下是解释。
SQL_CALC_FOUND_ROWS正在计算有多少行并将用于分页,因此它会计算总记录数,即使只显示20个。
DISTINCT将停止显示重复的行。
用户名来自用户表。
专辑,album_permission。它检查专辑是否为私有,如果是,则通过user_id检查用户是否具有权限。
我认为休息很容易理解,但如果您需要了解更多信息,请询问。
我真的很沮丧这个查询和网站很慢或无法打开有时导致此查询。请帮忙
SQL query: EXPLAIN select SQL_CALC_FOUND_ROWS DISTINCT media.*, username from album as album, album_permission as permission, user as user, media as media , word_tag as word_tag, tag as tag where ((media.album_id = album.album_id and album.private = 'yes' and album.album_id = permission.album_id and (permission.email = '' or permission.user_id = '') ) or (media.album_id = album.album_id and album.private = 'no' ) or media.album_id = '0' ) and media.status = '1' and media.user_id = user.user_id and word_tag.media_id = media.media_id and word_tag.tag_id = tag.tag_id and tag.name in ('justin','bieber','malfunction','katherine','heigl','wardrobe','cinetube') and media.media_type = 'video' and media.media_id not in ('YHL6a5z8MV4') group by media.media_id order by RAND() ;
Rows: 6
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE permission system album_id NULL NULL NULL 1 Using temporary; Using filesort
1 SIMPLE album ALL PRIMARY NULL NULL NULL 68
1 SIMPLE word_tag ALL media_id NULL NULL NULL 88383 Using where; Using join buffer
1 SIMPLE media eq_ref media_id,album_id media_id 34 _site.word_tag.media_id 1 Using where
1 SIMPLE tag eq_ref PRIMARY PRIMARY 4 _site.word_tag.tag_id 1 Using where
1 SIMPLE user eq_ref PRIMARY PRIMARY 34 _site.media.user_id 1
表结构http://pastie.org/912388此链接具有表转储,您可以在phpmyadmin中执行或运行它并查看表的结构。
答案 0 :(得分:3)
你可以做的最好的事情就是运行查询,但在它前面放一个EXPLAIN
,并分析结果。
在不知道该查询中所有表的结构(尤其是索引)的情况下,我们很难给出一个好的答案。
从这开始:Optimizing Queries with EXPLAIN。
如果你不能按照那里的建议取得任何进展,那么张贴你的桌子的结构,我们可以从那里帮助你。
答案 1 :(得分:1)
我首先抛弃ORDER BY RAND()。这是一个巨大的性能杀手。请参阅http://www.paperplanes.de/2008/4/24/mysql_nonos_order_by_rand.html和http://jan.kneschke.de/projects/mysql/order-by-rand/。
我建议您在选择结果后在代码中进行随机化。
答案 2 :(得分:1)
免责声明:我通常使用SQL Server而非MySQL,这是我第一次尝试实施MySQL Explain计划!特别是我假设它应该从上到下阅读。如果我错了,请有人纠正我!
但是,如果我正确地理解了它,那就是word_tag
表说它有88383行。它可以选择一个可能的索引(possible_keys = media_id),但它实际上选择不使用索引(key = null)。
原因似乎是查询中唯一可以限制从word_tag返回的行数的是加入word_tag.media_id = media.media_id and word_tag.tag_id = tag.tag_id
,但media
和tag
都不是直到后来才看你能告诉我这两个表有多少行吗?
编辑:实际上,EXPLAIN中显示了34行和4行。如果您在包含word_tag
和tag_id
列的media_id
上添加索引,该怎么办?如果这不会改变计划,可以尝试在这些表http://dev.mysql.com/doc/refman/5.0/en/analyze-table.html
另外。
如果删除LIMIT,结果集会返回多少行(即SQL_CALC_FOUND_ROWS的值是多少)?
如果删除DISTINCT怎么办?那么多少行?
答案 3 :(得分:0)
您是否尝试删除'ORDER BY RAND()',看看是否有所作为?
答案 4 :(得分:0)
正在讨论使用SQL_CALC_FOUND_ROWS
:
http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/
测试您的查询,禁用此选项,看看它是否有所不同(性能)。如果是这样,您可能需要找到一种不同的方法来查找结果集的行数。