5

私は高度なクエリを初めて使用するので、概念的に何か間違っている可能性があります。データベースに 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 のサンプルは、レコードが少ないため高速に実行されますが、自分のサーバーでレコードを複製しようとすると、クエリはわずか数レコードで高速に実行され、100 万のレコードを追加した後は非常に遅くなりました。

結果をすばやく取得する方法はありますか?

4

6 に答える 6

0

私はそうは思いません。このテーブルをそのまま使用すると、これらすべてのLIKEs を使用して高速に実行できるとは思えません。それらはばかげた回数実行する必要があります。

これらの値が固定されている場合、 and などと呼ばれるテーブルに新しい列を追加し、abc_like_yellowそれらabc_like_sporkの値を一度入力すると、その列から簡単にクエリを実行できます。

ただし、これを動的に実行しようとすると、うまくいかない可能性があります。

于 2013-04-11T22:47:59.117 に答える
0

サーバーが何百万ものエントリをスキャンする必要がある場合、クエリを迅速に処理するほど強力ではない可能性があります.

一般に、Web サイトの速度を向上させるには、 CloudFlareを試すことができます。

特に SQL を高速化しようとしている場合は、Google Cloud SQLが役立つ可能性があります。Google の強力なサーバーは、Google 検索の実行時などに、数十億の SQL エントリをスキャンするように設計されています。

エラーが返されない限り、上記の 2 つのサービスはクエリ時間を大幅に短縮するのに役立ちます。

お役に立てれば幸いです!

VCNinc
于 2013-05-02T05:54:55.857 に答える
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/>";
}

私が行った他の試みと比較して、今ではとても簡単に思えます。

于 2013-04-12T18:31:53.047 に答える
0

私たちが参加しusernameているので、この列のインデックスが物事をスピードアップする可能性があります.

また、左結合ではなく内部結合を使用できますか? これにより、クエリを大幅に高速化することもできます。

最後に、必要に応じて、データベースに順序付けを行うのではなく、メモリ内で順序付けを行うことができます (つまり、返された結果セットを順序付けます)。

于 2013-04-11T22:52:03.237 に答える