这是一些改编自phpBB的代码。我可以告诉它正在尝试删除所有主题,其中唯一的海报是目标用户。
(请注意,出于测试目的,我将最终查询从DELETE更改为SELECT)
<?php
$user_id = 66275;
mysql_connect('localhost', 'username', 'password');
mysql_select_db('db_name');
$start = microtime(true);
$total = 0;
define('POSTS_TABLE', 'phpbb_posts');
define('TOPICS_TABLE', 'phpbb_topics');
$sql = 'SELECT topic_id, COUNT(post_id) AS total_posts
FROM ' . POSTS_TABLE . "
WHERE poster_id = $user_id
GROUP BY topic_id";
$result = mysql_query($sql);
$topic_id_ary = array();
while ($row = mysql_fetch_assoc($result))
{
$topic_id_ary[$row['topic_id']] = $row['total_posts'];
}
mysql_free_result($result);
if (sizeof($topic_id_ary))
{
$sql = 'SELECT topic_id, topic_replies, topic_replies_real
FROM ' . TOPICS_TABLE . '
WHERE ' . sql_in_set('topic_id', array_keys($topic_id_ary));
$result = mysql_query($sql);
$del_topic_ary = array();
while ($row = mysql_fetch_assoc($result))
{
if (max($row['topic_replies'], $row['topic_replies_real']) + 1 == $topic_id_ary[$row['topic_id']])
{
$del_topic_ary[] = $row['topic_id'];
}
}
mysql_free_result($result);
if (sizeof($del_topic_ary))
{
$sql = 'SELECT topic_id FROM ' . TOPICS_TABLE . '
WHERE ' . sql_in_set('topic_id', $del_topic_ary);
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result))
{
$total++;
echo $row[topic_id] . "\r\n";
}
}
}
function sql_in_set($field, $array, $negate = false, $allow_empty_set = false)
{
if (!sizeof($array))
{
if (!$allow_empty_set)
{
// Print the backtrace to help identifying the location of the problematic code
$this->sql_error('No values specified for SQL IN comparison');
}
else
{
// NOT IN () actually means everything so use a tautology
if ($negate)
{
return '1=1';
}
// IN () actually means nothing so use a contradiction
else
{
return '1=0';
}
}
}
if (!is_array($array))
{
$array = array($array);
}
if (sizeof($array) == 1)
{
@reset($array);
$var = current($array);
return $field . ($negate ? ' <> ' : ' = ') . $var;
}
else
{
return $field . ($negate ? ' NOT IN ' : ' IN ') . '(' . implode(', ', $array) . ')';
}
}
$elapsed = microtime(true) - $start;
echo "\r\ntook $elapsed seconds";
echo "\r\ngot $total rows back";
?>
这会进行三次查询。首先获取目标用户发布的所有主题以及他们在每个主题中发布的次数。第二个获取第一个查询中每个主题实际拥有的回复数。然后是一些PHP代码,以查看哪些主题已由目标用户发布了所有帖子。之后代码(在我更改之前)删除所有这些主题。
总的来说,在我看来,通过这样做可以更好地写出来:
SELECT t.topic_id
FROM phpbb_topics AS t
JOIN phpbb_posts AS p1
ON p1.topic_id = t.topic_id
AND p1.poster_id = $poster_id
LEFT JOIN phpbb_posts AS p2
ON p2.topic_id = t.topic_id
AND p2.poster_id <> $poster_id
WHERE p2.poster_id IS NULL;
或许这个:
SELECT t.topic_id
FROM phpbb_topics AS t
JOIN phpbb_posts AS p1
ON p1.topic_id = t.topic_id
AND p1.poster_id = $poster_id
AND t.topic_poster = $poster_id
AND t.topic_last_poster_id = $poster_id
LEFT JOIN phpbb_posts AS p2
ON p2.topic_id = t.topic_id
AND p2.poster_id <> $poster_id
WHERE p2.poster_id IS NULL
由于MySQLs caching测试这实际上非常困难,但是...从我能够做的测试看起来像phpBB目前正在做的方式实际上更快。这让我很惊讶。
有什么想法吗?
答案 0 :(得分:1)
我认为你走在正确的轨道上。尝试将索引添加到您在联接中使用的所有列,因为这通常会大大提高连接速度。