我有一个视频网站,其中一些表格是:
代码
id ~ int(11), auto-increment [PRIMARY KEY]
tag_name ~ varchar(255)
videotags
tag_id ~ int(11) [PRIMARY KEY]
video_id ~ int(11) [PRIMARY KEY]
视频
id ~ int(11), auto-increment [PRIMARY KEY]
video_name ~ varchar(255)
现在,此时标签表具有> 1000行,而视频标签表具有> 32000行。因此,当我运行查询以显示从最常见到最不常见的所有标记时,执行时需要> 15秒。
我正在使用PHP和我的代码(为简单而淡化)如下:
foreach ($database->query("SELECT tag_name,COUNT(tag_id) AS 'tag_count' FROM tags LEFT OUTER JOIN videotags ON tags.id=videotags.tag_id GROUP BY tags.id ORDER BY tag_count DESC") as $tags)
{
echo $tags["tag_name"] . ', ';
}
现在请记住,这是100%准确对我来说并不像快速那么重要。因此,即使查询每天执行一次并且其结果在当天的剩余时间内使用,我也不在乎。
我对MySQL / PHP缓存一无所知所以请帮助!
答案 0 :(得分:3)
MarkR提到了索引。请确保:
create index videotags_tag_id on videotags(tag_id);
答案 1 :(得分:2)
32,000行仍然是一张小桌子 - 你的表现不可能那么糟糕。
你可以在你的查询上运行EXPLAIN
- 我猜你的索引在某处错了。
你在问题中说:
tag_id ~ int(11) [PRIMARY KEY]
video_id ~ int(11) [PRIMARY KEY]
他们肯定是那个顺序吗?如果没有,那么它将不会使用索引。
答案 2 :(得分:0)
我认为最好的办法是创建一些汇总表,并在事情发生变化时进行维护。
上面的查询需要扫描表中的所有行,以便通过以下方式查找聚合: - 没有WHERE CLAUSE。没有where子句的查询没有优化的希望,因为它必须检查每一行。
修复方法是创建一个摘要表,其中包含与该查询(或类似)结果相同的数据,当数据发生变化或发生显着变化时,您将不得不维护这些数据。
只有您可以根据应用程序和数据的性质决定是否适合按计划,每次更新或某种组合更新摘要表。
当你正在进行连接时,正确的索引仍然是有益的,但你知道,对,并且已经完成了吗?
答案 3 :(得分:0)
您使用的是InnoDB还是MyISAM?在MyISAM中COUNT基本上是免费的,但在InnoDB中它必须实际计算行数。