0

私は自分の DB をより最適化しようとしており、インデックス作成を始めていますが、正しく行う方法がわかりません。

私はこのクエリを持っています:

$year = date("Y");
$thisYear = $year;
//$nextYear = $thisYear + 1; 
$sql = mysql_query("SELECT SUM(points) as userpoints
                                          FROM ".$prefix."_publicpoints
                                          WHERE date BETWEEN '$thisYear" . "-01-01' AND '$thisYear" . "-12-31' AND fk_player_id = $playerid");
$row = mysql_fetch_assoc($sql); 
$userPoints = $row['userpoints'];

$sql = mysql_query("SELECT 
                       fk_player_id
                    FROM ".$prefix."_publicpoints
                    WHERE date BETWEEN '$thisYear" . "-01-01' AND '$thisYear" . "-12-31'
                    GROUP BY fk_player_id
                    HAVING SUM(points) > $userPoints");
$row = mysql_fetch_assoc($sql);
$userWrank = mysql_num_rows($sql)+1;

これをインデックス化する方法がわかりませんか?fk_player_id のインデックスを作成しようとしましたが、まだすべての行を調べています (287937)。

EXPLAINでこれを返す日付フィールドにインデックスを付けました:

1 SIMPLE nf_publicpoints range IDXdate IDXdate 3 NULL 143969 プッシュ条件で where を使用。一時的な使用...

また、同じテーブルへの呼び出しが 2 つあります。1 回で実行できますか?

これをどのようにインデックス化するか、またはよりスマートに行うことができますか?

4

3 に答える 3

1

インデックス作成については、必ず時間をかけて読んでください。それについてはたくさん書かれています。何が起こっているのかを理解することが重要です。

大まかに言えば、インデックスはテーブルの行に順序付けを課します。

簡単にするために、テーブルが単なる大きな CSV ファイルであると想像してください。行が挿入されるたびに、最後に挿入されます。したがって、テーブルの「自然な」順序付けは、行が挿入された順序にすぎません。

非常に初歩的なスプレッドシート アプリケーションにその CSV ファイルが読み込まれていると想像してください。このスプレッドシートは、データを表示し、行に順番に番号を付けるだけです。

ここで、3 番目の列に値 "M" を持つすべての行を検索する必要があるとします。利用可能なものを考えると、選択肢は 1 つだけです。テーブルをスキャンして、各行の 3 列目の値をチェックします。行数が多い場合、この方法 (「テーブル スキャン」) には時間がかかることがあります。

このテーブルに加えて、インデックスがあるとします。この特定のインデックスは、3 列目の値のインデックスです。インデックスには、3 番目の列のすべての値が意味のある順序 (アルファベット順など) で一覧表示され、それぞれについて、その値が表示される行番号のリストが提供されます。

これで、3 番目の列の値が M であるすべての行を見つけるための優れた戦略ができました! たとえば、バイナリ検索を実行できます。テーブル スキャンでは N 行 (N は行数) を検索する必要がありますが、バイナリ検索では、最悪の場合、log-n インデックス エントリのみを検索する必要があります。うわー、それは確かにずっと簡単です!

もちろん、このインデックスがあり、テーブルに行を追加する場合 (概念的なテーブルがそのように機能するため、最後に)、毎回インデックスを更新する必要があります。したがって、新しい行を書き込んでいる間は少し多くの作業を行いますが、何かを検索するときは多くの時間を節約できます。

したがって、一般に、インデックス作成では、読み取り効率と書き込み効率の間にトレードオフが生じます。インデックスがない場合、挿入は非常に高速になります。データベース エンジンはテーブルに行を追加するだけです。インデックスを追加すると、エンジンは挿入の実行中に各インデックスを更新する必要があります。

一方、読み取りははるかに高速になります。

これで最初の 2 つの質問がカバーされることを願っています (他の人が答えているように、適切なバランスを見つける必要があります)。

3 番目のシナリオはもう少し複雑です。LIKE を使用している場合、インデックス エンジンは通常、最初の "%" までの読み取り速度を向上させます。つまり、「foo%bar%」のように WHERE 列を選択している場合、データベースはインデックスを使用して、列が「foo」で始まるすべての行を検索し、その中間行セットをスキャンしてサブセットを見つける必要があります。 「バー」が含まれています。SELECT ... WHERE column LIKE '%bar%' はインデックスを使用できません。理由がわかると思います。

最後に、複数の列のインデックスについて考え始める必要があります。概念は同じで、LIKE のものと同様に動作します。基本的に、(a、b、c) にインデックスがある場合、エンジンは可能な限り左から右にインデックスを使用し続けます。したがって、列 a の検索では、(a,b) の検索と同様に、(a,b,c) インデックスが使用される場合があります。ただし、WHERE b=5 AND c=1 を検索する場合、エンジンは完全なテーブル スキャンを実行する必要があります)。

これが少し光を当てるのに役立つことを願っています. 特定のデータベース サーバーのドキュメントを読むこともお勧めします。クエリ プランナーがインデックスを実装して使用する方法は、さまざまです。

詳細と例については、http: //blog.sqlauthority.com/category/sql-index/を参照してください。

于 2013-02-09T11:37:22.460 に答える
0

ルックアップで評価される主な基準が日付列にどのように評価されるかを見て、日付列にインデックスを付けてみませんか?

于 2013-02-09T11:36:50.700 に答える
0

日付列にインデックスを作成してみてください。fk_payer_id のインデックス作成は、このクエリには役立ちません。うまくいかない場合 - 説明を貼り付けてください...

Mysql のインデックスの詳細については、http://hackmysql.com/case1 を参照してください。

于 2013-02-09T11:28:15.360 に答える