什么是获取一行数据记录的最快方法?

时间:2016-06-29 15:19:28

标签: php mysql

所以我正在测试一个包含超过100万行数据的用户的大型数据库表,试图提出某种用户等级"但与使用这些数据的任何其他方式相比,它看起来非常慢,所以我想知道我是否采用了错误的方式。 我使用两列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已编入索引

这似乎加载得非常缓慢,而不是真的&#39;慢,但比我慢,所以我决定用它进行一些测试,并检查脚本使用以下方法执行多长时间:

<?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.';

根据1000次加载,平均加载时间为1.9468239237秒。

然后我在循环中添加了一个break;,当它发现你的排名时,可能会缩短处理时间但无济于事。

所以我的问题是,你有更好的方法来计算这样的东西吗?

3 个答案:

答案 0 :(得分:3)

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

SELECT t.*
FROM users u
INNER JOIN (
  SELECT id, points, IF(@rank IS NULL,@rank:=1,@rank:=@rank+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

答案 1 :(得分: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;

答案 2 :(得分:1)

我想尝试这样的事情

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 = ?