我是高级查询的新手,所以我可能有一些概念上的错误,因为当数据库有超过100万条记录时,我得到了这个回复我的查询......
ERROR 2013: Lost connection to MySQL server during query
是的!它实际上需要很长时间才能在它完成之前呕吐。
我的疑问是......
SELECT users.username,
table_1.field_abc, table_1.field_def,
table_2.field_ghi, table_2.field_jkl
FROM users
LEFT JOIN table_1 ON table_1.username = users.username
LEFT JOIN table_2 ON table_2.username = users.username
WHERE
table_1.field_abc REGEXP "(spork|yellow)" OR
table_1.field_def REGEXP "(spork|yellow)" OR
table_2.field_ghi REGEXP "(spork|yellow)" OR
table_2.field_jkl REGEXP "(spork|yellow)"
GROUP BY users.username
ORDER BY
(
( CASE WHEN table_1.field_abc LIKE "%spork%" THEN 1 ELSE 0 END ) +
( CASE WHEN table_1.field_abc LIKE "%yellow%" THEN 1 ELSE 0 END ) +
( CASE WHEN table_1.field_def LIKE "%spork%" THEN 1 ELSE 0 END ) +
( CASE WHEN table_1.field_def LIKE "%yellow%" THEN 1 ELSE 0 END ) +
( CASE WHEN table_2.field_ghi LIKE "%spork%" THEN 1 ELSE 0 END ) +
( CASE WHEN table_2.field_ghi LIKE "%yellow%" THEN 1 ELSE 0 END ) +
( CASE WHEN table_2.field_jkl LIKE "%spork%" THEN 1 ELSE 0 END ) +
( CASE WHEN table_2.field_jkl LIKE "%yellow%" THEN 1 ELSE 0 END )
)DESC;
我在http://sqlfiddle.com/#!2/cbbda/28
发布了一个示例数据集(只有几条记录)sqlfiddle上的示例运行速度很快,因为只有少量记录,但我尝试在我自己的服务器上复制记录,查询只用几条记录快速运行,而且在我添加了一百万条记录后速度非常慢。
有没有办法快速获得我的结果?
答案 0 :(得分:1)
好伙计......在你的帮助下,我们有了解决方案...见http://sqlfiddle.com/#!2/fcfbd/5 但我仍然有一个问题...
我改变了表格以添加索引......
ALTER TABLE `users` ADD FULLTEXT ( `username` );
ALTER TABLE `table_1` ADD FULLTEXT ( `field_abc`,`field_def` );
ALTER TABLE `table_2` ADD FULLTEXT ( `field_ghi`,`field_jkl` );
然后我接受了@Barmar的建议并将代码改为此...
SELECT users.username,
table_1.field_abc, table_1.field_def,
table_2.field_ghi, table_2.field_jkl
FROM users
LEFT JOIN table_1 ON table_1.username = users.username
LEFT JOIN table_2 ON table_2.username = users.username
WHERE
MATCH(table_1.field_abc,table_1.field_def,table_2.field_ghi,table_2.field_jkl)
AGAINST ("spork yellow" IN BOOLEAN MODE)
GROUP BY users.username
ORDER BY
(
( CASE WHEN MATCH(table_1.field_abc) AGAINST ("spork" IN BOOLEAN MODE) THEN 1 ELSE 0 END ) +
( CASE WHEN MATCH(table_1.field_abc) AGAINST ("yellow" IN BOOLEAN MODE) THEN 1 ELSE 0 END ) +
( CASE WHEN MATCH(table_1.field_def) AGAINST ("spork" IN BOOLEAN MODE) THEN 1 ELSE 0 END ) +
( CASE WHEN MATCH(table_1.field_def) AGAINST ("yellow" IN BOOLEAN MODE) THEN 1 ELSE 0 END ) +
( CASE WHEN MATCH(table_2.field_ghi) AGAINST ("spork" IN BOOLEAN MODE) THEN 1 ELSE 0 END ) +
( CASE WHEN MATCH(table_2.field_ghi) AGAINST ("yellow" IN BOOLEAN MODE) THEN 1 ELSE 0 END ) +
( CASE WHEN MATCH(table_2.field_ghi) AGAINST ("spork" IN BOOLEAN MODE) THEN 1 ELSE 0 END ) +
( CASE WHEN MATCH(table_2.field_ghi) AGAINST ("yellow" IN BOOLEAN MODE) THEN 1 ELSE 0 END )
)DESC;
在我的真实数据库中有超过1,000,000条记录,我的结果是6.5027秒。那比A ...好多了,花了很长时间才发现它!
我现在唯一的问题是......为什么它只适用于IN BOOLEAN MODE而不是http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html#function_match或http://dev.mysql.com/doc/refman/5.5/en/fulltext-search.html中提到的其他两个选项?
答案 1 :(得分:0)
我不这么认为 - 有了这张桌子,我怀疑你会让它们快速运行所有这些LIKE
。那些必须经历荒谬的次数。
如果这些值是固定的,那么您可以向名为abc_like_yellow
和abc_like_spork
等的表添加新列,并将这些值填充一次,然后您可以轻松查询该列
但如果你想动态地做这件事,你可能会运气不好。
答案 2 :(得分:0)
由于我们加入了username
,因此此列上的索引可能会加快速度。
此外,您是否可以使用内部联接而不是左联接?这也可以在很大程度上加快查询速度。
最后,如果有必要,可以在内存中完成排序,而不是要求数据库执行此操作(即在返回结果集后对其进行排序)。
答案 3 :(得分:0)
我正在使用我的第一个解决方案,但发现它给出了一些我无法弄清楚的误报,所以我想出了这个......
(SELECT username, MATCH(field_abc,field_def) AGAINST ("spork yellow" IN BOOLEAN MODE) AS score FROM table_1 HAVING score>0)
UNION ALL
(SELECT username, MATCH(field_ghi,field_jkl) AGAINST ("spork yellow" IN BOOLEAN MODE) AS score FROM table_2 HAVING score >0)
由于每个记录都是单独返回的,我无法使用GROUP BY
我在查询完成后添加了这个PHP代码:
while($row = mysql_fetch_array($result) )
{
if( in_array($row['username'],$usernames) )
{
$usernames_count[$row['username']] += $row['score'];
}
else
{
array_push($usernames,$row['username']);
$usernames_count[$row['username']]=$row['score'];
}
}
arsort($usernames_count); // Sort the results high->low
foreach($usernames_count as $key=>$value)
{
echo "Username: ".$key." had a score of ".$value." in the search results<br/>";
}
与我做的其他尝试相比,它现在看起来很简单。
答案 4 :(得分:0)
当您的服务器必须扫描数百万条目时,它可能不够强大,无法快速处理查询。
一般来说,为了提高网站的速度,您可以尝试CloudFlare
如果您专门尝试加速SQL,Google Cloud SQL可能会有所帮助。 Google功能强大的服务器旨在扫描数十亿条SQL条目,例如执行Google搜索时。
只要没有返回错误,上述两项服务将有助于大大加快您的查询时间。
我希望我能帮忙!
VCNinc
答案 5 :(得分:0)
如果您有权访问SQL Server,请在SQL Server中突出显示您的完整查询,然后单击+ L
这将显示查询执行计划。根据这些结果优化查询;
例如,如果您看到表扫描,那么索引可能会有所帮助。 编写不使用术语distinct的查询。 如果订单不重要,请不要订购结果。
在您的样本中,复杂的最后一组订单非常昂贵。
请按照以下步骤操作: 将核心信息拉入临时表,其中包含9个额外列(类型为int,最初设置为0) 填充核心数据后,根据0或1条件更新8列中的每一列 将最后一列更新为其他8列的总和 从表中检索信息,只有一个基于第9列的“订单”。
根据我的经验,与在内部执行订单相比,这种方法只需要20%的时间。