2016-06-29 5 views
4

私は大規模なデータベーステーブルを使用していましたが、100万行を超えるデータがあり、何らかの「ユーザーランク」を思いついていますが、他の方法と比較して非常に遅いです。このデータを使用して、間違った方法で行っているのかどうか疑問に思っていました。 私は、2つの列idpointsを持つデータのすべての行をポイント単位でグルーピングしていますので、同じポイントの人々は同じランクになり、降順で並べ替えられます。データの行のレコードを取得する最も速い方法は何ですか?

ここでクイックスローが一緒だ、私はそれをテストしました:

<?php 
session_start(); 
$rank = 0; 
$query = $conn->prepare("SELECT id, points FROM users GROUP BY points ORDER BY points DESC"); 
$query->execute(); 
foreach($query as $result){ 
    $rank += 1; 
    if($result['id'] == $_SESSION['myid']){ 
     echo '' . $_SESSION['myuser'] . ' is rank ' . number_format($rank) . ' globally.'; 
    } 
} 

pointsid

この

をインデックス化しているが、私は思いよりもかなりゆっくりと、本当に「ゆっくりではあるが遅くないロードするように見えました私はそれを使っていくつかのテストを行い、次のメソッドを使用して実行するスクリプトの長さを確認することにしました:

<?php 
$starttime = microtime(true); 
session_start(); 
$rank = 0; 
$query = $conn->prepare("SELECT id, points FROM users GROUP BY points ORDER BY points DESC"); 
$query->execute(); 
foreach($query as $result){ 
    $rank += 1; 
    if($result['id'] == $_SESSION['myid']){ 
     echo '' . $_SESSION['myuser'] . ' is rank ' . number_format($rank) . ' globally.'; 
    } 
} 
$endtime = microtime(true); 
$duration = $endtime - $starttime; 
echo '<br /><br />This page took ' . $duration . ' seconds to load.'; 

これは、平均負荷が1.9468239237で、負荷が1000に基づいています。

それは多分それは、処理時間を短縮するが、無駄にだろうと考え、あなたのランクを見つけたときに私は、ループ内でbreak;を追加しました。

私の質問は、このような何かを計算する良い方法はありますか?

+1

あなたは、インデックスが実際に使用されているかどうかを確認するために、あなたのクエリにEXPLAINをやっていますか?あなたはすべてを取得したい場合は、 '場合($結果[ 'ID'] == $ _SESSION [ 'MYID']){'クエリがランダムな返しに、後で比較するために、 'id'をpoints' BY' GROUPを行うべきではありません –

+3

'id' http://sqlfiddle.com/#!9/56bc9d/1 – Alex

+0

@ chris85しかし、それは1行だけになるだろう...それはみんなのポイントに基づいて、あなたの数を計算する必要がありますそれ以外の場合は、常にあなたがしていることを返します#1にランクされました。 – SmurfTheSmurf

答えて

3

http://sqlfiddle.com/#!9/05189/3

SELECT t.* 
FROM users u 
INNER JOIN (
    SELECT id, points, IF(@rank IS NULL,@rank:=1,@rank:[email protected]+1) rank 
    FROM users 
    ORDER BY points DESC) t 
ON u.id = t.id 
WHERE u.id = 3; # <- 3 is id you are looking for 
+0

これは 'id'が何であるかに関係なく常に1を返します。 – SmurfTheSmurf

+0

何?私のバイブルをチェックしましたか? – Alex

+0

これはユーザーをグループ化するようには表示されません。 –

1

あなたはこれまであなたのクエリを変更することを試みることができる:

SELECT id, Name, 1+(SELECT count(*) from users u1 WHERE u1.Points > u1.Points) as Rank, Points 
FROM users u WHERE u.id = your_id; 
1

私はあなたのユーザーのIDでクエリを作成し、この

SELECT users.id, ranks.rank 
FROM users 
INNER JOIN (
    SELECT points, ROW_NUMBER() AS rank 
    FROM users 
    GROUP BY points 
    ORDER BY points DESC 
) ranks ON users.points = ranks.points 
WHERE users.id = ? 

のようなものを試してみたいと思います。

編集: MySQLにはROW_NUMBER()関数がありません。これは、代わりに動作するはずです:

SELECT users.id, ranks.rank 
FROM users 
INNER JOIN (
    SELECT t1.points, @rank := @rank + 1 AS rank 
    FROM (
     SELECT points 
     FROM users 
     GROUP BY points 
     ORDER BY points DESC 
    ) t1, (SELECT @rank := 0) t2 
) ranks ON users.points = ranks.points 
WHERE users.id = ? 
関連する問題