1

MySQLデータベースのテーブルからランダムに置き換えることなく、いくつかのIDを1つずつ描画するPHPコードが必要です。

今、私はそれを次のように実装します:

ボックスと呼ばれるテーブルがあります

CREATE TABLE box
(
id INT UNSIGNED AUTO_INCREMENT,
PRIMARY KEY (id)
);

15個のレコードが含まれているとしましょう。

id:
=====
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
=====

描画されたIDは記録され、次の描画で除外されます。

例えば、

最初は、描画用のSQLは次のようになります。

SELECT id FROM box RAND() LIMIT 1;`.

結果が4だとします。

次に、4を描画しました。描画用の次のSQLは、

SELECT id FROM box WHERE id != 4 ORDER BY RAND() LIMIT 1;

今回は結果が6だとしましょう。

つまり、4と6を描画したので、描画用の次のSQLは次のようになります。

SELECT id FROM box WHERE id != 4 AND id != 6 ORDER BY RAND() LIMIT 1;"

問題はそれです:

テーブル「ボックス」に2000レコードが含まれていて、1000以上のIDを描画した場合、描画用の次のSQLは非常に長くなります。SQLステートメントが長くなると、MySQLのプログラムまたはプロセスの実行が遅くなるのではないでしょうか。はいの場合、この問題を解決するための解決策/設計/アルゴリズムはありますか?テーブル内のレコードが増える可能性があるため、描画前にIDでランダムなシーケンスを作成することはできません。


問題の詳細:

PHPコードは複数のユーザーによって呼び出されるため、各ユーザーは自分によって描画されたいくつかの異なるIDを持っています。

実際、私の現在の設計では、ユーザーによって描画されたIDはPHPセッション変数に格納されています。ユーザーが描画したい場合、セッション変数に格納されているIDは、上記のように描画SQLのためにアクセスされます。

4

4 に答える 4

1

ボックスのレコード数が固定されている場合は、ユーザーにより多くのスペースを使用するようにアプローチする傾向がありますが、実行速度は速くなります。アプローチでは、が原因で、次の値を取得するために全表スキャンが必要ですorder by rand()

代わりに、ユーザーごとに個別の「ボックス」を作成し、最初にランダムな順序付けを行います。

CREATE TABLE userbox (
    userboxid INT UNSIGNED AUTO_INCREMENT,
    int boxid,
    userid int,
    PRIMARY KEY (userboxid),
    KEY (userid, userboxid)
);

次に、ユーザーが起動したら、そのユーザーのボックスに挿入します。

insert into userbox
    select id, <userid>
    from box
    order by rand()

後続の取得では、次のようなselectステートメントが使用されます。

select boxid
from userbox
where userboxid > <last user box id> and userid = <userid>
limit 1

このアプローチの利点は、ボックスにデータを入力するオーバーヘッドの後、次のIDを取得するたびに、インデックス内の次の値を確認し、データページからボックスIDを取得するだけでよいことです。

于 2012-12-09T15:42:45.810 に答える
1

作成されたクエリのほとんどは、クエリとほぼ同じ時間がかかります。

ちなみに、クエリの条件はNOT INと同等であり、NOT INを適用する方が簡単かもしれません

SELECT * FROM box WHERE id NOT IN (a[0],a[1]...)

クエリのサイズの増加が MySQL の速度を低下させるかどうかについては、答えはノーです。

速度が低下しない理由についての記事はこちらです(クエリは not in と同等であることを思い出してください)。

于 2012-12-09T15:11:19.020 に答える
1

その数字が描かれたかどうかを示す別の列を表に追加してみませんか?

次に、クエリは次のようになります。

SELECT id FROM box WHERE drawn = 0 ORDER BY RAND() LIMIT 1

そして、その後:

UPDATE box SET drawn = 1 WHERE id = 43またはあなたが描いたID。

于 2012-12-09T15:10:11.613 に答える
0

各ユーザーが描いた数字用に別のテーブルを作成できます

user_id     id
  1         129
  1         832
  2         23
 ...

それから

SELECT id FROM box WHERE id NOT IN (SELECT id FROM user_drawn WHERE user_id=1) RAND() LIMIT 1;
于 2012-12-09T15:38:22.050 に答える