Php 加快(不可缓存的)MySQL查询

Php 加快(不可缓存的)MySQL查询,php,performance,mysqli,Php,Performance,Mysqli,我有一些PHP会话测试代码,以确保登录的用户是有效的。 我将解释一些函数:is\u logged\u in只检查是否设置了一些会话变量,test\u duplicate连接到数据库,检查是否有一行的列等于该值 function check_account(){ if(is_logged_in()){ // Destroy session if the user doesn't exist. if(test_duplicate("username", $_SESSION["us

我有一些PHP会话测试代码,以确保登录的用户是有效的。 我将解释一些函数:
is\u logged\u in
只检查是否设置了一些会话变量,
test\u duplicate
连接到数据库,检查是否有一行的列等于该值

function check_account(){
  if(is_logged_in()){
    // Destroy session if the user doesn't exist.
    if(test_duplicate("username", $_SESSION["user"])){
      session_destroy();
    }
  }

  if($_SESSION["valid_day"] != date("Ymd")){
    // Destroy session if the key has expired
    session_destroy();
  }
}



function test_duplicate($field, $value){
  $mysqli = database_connect();
  $statement = $mysqli->prepare("SELECT * FROM users WHERE " . $field . " = ?");
  $statement->bind_param("s", $value);
  $statement->execute();
  $statement->store_result();

  $rows = $statement->num_rows;
  if($rows > 0){
    return FALSE;
  }

  return TRUE;
}

function database_connect(){
  if(!isset($dbconnection)){
    $config = get_configuration();

    // Create connection
    $mysqli = new mysqli($config["hostname"], $config["username"], $config["password"], $config["database"]);

    if($mysqli->connect_error){
      die("<h1>Error 1 :: Critical backend failure</h1>");
    }

    if(!check_tables($mysqli)){
      die("<h1>Error 2 :: Critical backend failure</h1>");
    }

    $dbconnection = $mysqli;

    return $mysqli;
  }else{
    return $dbconnection;
  }
}
功能检查\u账户(){
如果(是否已登录){
//如果用户不存在,则销毁会话。
如果(测试重复(“用户名”、$\u会话[“用户”])){
会话_destroy();
}
}
如果($\会话[“有效日”!=日期(“Ymd”)){
//如果密钥已过期,则销毁会话
会话_destroy();
}
}
功能测试\u重复($field,$value){
$mysqli=数据库连接();
$statement=$mysqli->prepare(“从用户中选择*,其中“$field.”=?”;
$statement->bind_参数(“s”,$value);
$statement->execute();
$statement->store_result();
$rows=$statement->num\u行;
如果($rows>0){
返回FALSE;
}
返回TRUE;
}
函数数据库_connect(){
如果(!isset($dbconnection)){
$config=get_configuration();
//创建连接
$mysqli=newmysqli($config[“hostname”]、$config[“username”]、$config[“password”]、$config[“database”]);
如果($mysqli->connect\u error){
die(“错误1:严重后端故障”);
}
如果(!check_tables($mysqli)){
die(“错误2:严重后端故障”);
}
$dbconnection=$mysqli;
返回$mysqli;
}否则{
返回$dbconnection;
}
}
问题是:

  • test\u duplicate
    功能大约需要3-4秒才能完成
  • 缓存将不起作用,因为我需要测试该值(它将确定用户是否仍然存在于数据库中)
我目前的解决方案(我认为这些不是特别好):

  • 仅随机运行代码(即1/5的机会)
  • 没有运行代码(但是我不知道如何实现这个替代方案)
    • 我建议:

    • 添加调试代码以测量
      test\u duplicate
      函数中每行代码所需的时间
    • 缓存连接并在您的组件之间共享,如@jeroen在评论中建议的
    • 返回单个整数值,而不是使用
      select*
      选择所有字段。更好的做法是将其作为一个返回行的查询进行hadle,而不是将其作为一个返回单个值的标量查询进行hadle
    • 更新

      这里有一个查询,如果在
      username
      中有一行具有指定值,则返回1;如果不存在匹配行,则为0:

      select
        ifnull(
          (
            select
              1 as user_exists
            from
              dual
            where
              exists(
                select * from users where username = 'test2'
              )
          ), 0) as result
      from dual
      
      我建议:

    • 添加调试代码以测量
      test\u duplicate
      函数中每行代码所需的时间
    • 缓存连接并在您的组件之间共享,如@jeroen在评论中建议的
    • 返回单个整数值,而不是使用
      select*
      选择所有字段。更好的做法是将其作为一个返回行的查询进行hadle,而不是将其作为一个返回单个值的标量查询进行hadle
    • 更新

      这里有一个查询,如果在
      username
      中有一行具有指定值,则返回1;如果不存在匹配行,则为0:

      select
        ifnull(
          (
            select
              1 as user_exists
            from
              dual
            where
              exists(
                select * from users where username = 'test2'
              )
          ), 0) as result
      from dual
      

      您的数据库表是否已编制索引?正确的索引使读取操作非常快,即使是在非常大的(1M+行)表上。除了前面的建议:如果
      test\u duplicate()
      导致问题,您应该发布该函数,不是工作正常的代码。您是否已经对这个特定的独立函数进行了基准测试,以确保它实际上需要4秒钟才能完成?您可能会有其他开销导致您的延迟-特别是如果它在Workbench中运行得很快,您会认为它是全球性的。若要访问函数内全局作用域上的变量,必须传入该变量或在函数内使用全局关键字。你两个都没有做@山姆:祝你好运,那么你的数据库表被索引了吗?正确的索引使读取操作非常快,即使是在非常大的(1M+行)表上。除了前面的建议:如果
      test\u duplicate()
      导致问题,您应该发布该函数,不是工作正常的代码。您是否已经对这个特定的独立函数进行了基准测试,以确保它实际上需要4秒钟才能完成?您可能会有其他开销导致您的延迟-特别是如果它在Workbench中运行得很快,您会认为它是全球性的。若要访问函数内全局作用域上的变量,必须传入该变量或在函数内使用全局关键字。你两个都没有做@山姆:祝你好运,那么你的意思是
      限制1
      ?另外,
      数据库连接
      函数占用的时间最长,我在这里定义了
      $mysqli
      ,那么你的意思是
      限制1
      ?另外,
      数据库连接
      函数占用的时间最长,我在这里定义了
      $mysqli