[解決済み] MySQLのORDER BY RAND()関数を最適化するにはどうしたらいいですか?
2023-03-26 20:33:16
質問
クエリを最適化したいので、以下のことを調べています。
mysql-slow.log
.
私の遅いクエリのほとんどは
ORDER BY RAND()
. この問題を解決するための実際のソリューションが見つかりません。可能な解決策は次のとおりです。
MySQLPerformanceBlog
にありますが、これで十分だとは思えません。最適化されていない (あるいは頻繁に更新される、ユーザーが管理する) テーブルでは、うまくいかないか、あるいは、自分の
PHP
-で生成されたランダムな行を選択する前に、2つ以上のクエリを実行する必要があります。
この問題に対する解決策はありますか?
ダミーの例です。
SELECT accomodation.ac_id,
accomodation.ac_status,
accomodation.ac_name,
accomodation.ac_status,
accomodation.ac_images
FROM accomodation, accomodation_category
WHERE accomodation.ac_status != 'draft'
AND accomodation.ac_category = accomodation_category.acat_id
AND accomodation_category.acat_slug != 'vendeglatohely'
AND ac_images != 'b:0;'
ORDER BY
RAND()
LIMIT 1
どのように解決するのですか?
これを試してみてください。
SELECT *
FROM (
SELECT @cnt := COUNT(*) + 1,
@lim := 10
FROM t_random
) vars
STRAIGHT_JOIN
(
SELECT r.*,
@lim := @lim - 1
FROM t_random r
WHERE (@cnt := @cnt - 1)
AND RAND(20090301) < @lim / @cnt
) i
これは特に
MyISAM
で特に効率的です (つまり
COUNT(*)
は瞬間的なものなので)、しかし
InnoDB
は
10
よりも何倍も効率的です。
ORDER BY RAND()
.
ここでの主な考え方は、ソートを行わず、2つの変数を保持して計算することです。
running probability
を計算することです。
詳しくは私のブログのこの記事をご覧ください。
更新しました。
ランダムに1つのレコードを選択する必要がある場合、これを試してみてください。
SELECT aco.*
FROM (
SELECT minid + FLOOR((maxid - minid) * RAND()) AS randid
FROM (
SELECT MAX(ac_id) AS maxid, MIN(ac_id) AS minid
FROM accomodation
) q
) q2
JOIN accomodation aco
ON aco.ac_id =
COALESCE
(
(
SELECT accomodation.ac_id
FROM accomodation
WHERE ac_id > randid
AND ac_status != 'draft'
AND ac_images != 'b:0;'
AND NOT EXISTS
(
SELECT NULL
FROM accomodation_category
WHERE acat_id = ac_category
AND acat_slug = 'vendeglatohely'
)
ORDER BY
ac_id
LIMIT 1
),
(
SELECT accomodation.ac_id
FROM accomodation
WHERE ac_status != 'draft'
AND ac_images != 'b:0;'
AND NOT EXISTS
(
SELECT NULL
FROM accomodation_category
WHERE acat_id = ac_category
AND acat_slug = 'vendeglatohely'
)
ORDER BY
ac_id
LIMIT 1
)
)
これは、あなたの
ac_id
が多かれ少なかれ均等に配置されていると仮定しています。
関連
-
MySQLによる既存テーブルのパーティショニングの実装
-
[解決済み] PHPでSQLインジェクションを防ぐにはどうしたらいいですか?
-
[解決済み] リストからランダムに項目を選択するにはどうすればよいですか?
-
[解決済み] Pythonスクリプトのプロファイリングはどのように行うのですか?
-
[解決済み] MySQLでコマンドラインを使用してユーザーアカウントのリストを取得するにはどうすればよいですか?
-
[解決済み] MySQLのクエリ結果をCSV形式で出力するにはどうすればよいですか?
-
[解決済み] ブーリアン値を格納するために使用するMySQLデータ型
-
[解決済み] Eclipseを高速化する方法とは?
-
[解決済み] utf8_general_ciとutf8_unicode_ciの違いは何ですか?
-
[解決済み] ランダムな英数字の文字列を生成するにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
MySQLインストールチュートリアル(Windows用)詳細
-
MySQLの悲観的ロックと楽観的ロックの実装スキーム
-
[解決済み】マルチパート識別子をバインドできませんでした。
-
MySQLにおけるvarchar型とchar型の違い
-
MySQL 接続タイムアウト。エラー SQLSTATE[HY000] [2002] 接続がタイムアウトしました 解決済み
-
[解決済み] どのトランザクションが「テーブルメタデータのロック待ち」状態を引き起こしているかを確認するにはどうすればよいですか?
-
[解決済み] mysqladminのフラッシュホストでブロックを解除する方法
-
[解決済み] Mysqlでidを使用してテーブルから多くの行を削除する
-
[解決済み] MySQLデータベースの名前を素早く変更する(スキーマ名を変更する)方法は?
-
[解決済み] MySQLは600K行からランダムな10行を高速に選択する