分页时显然更好:将结果存储在$ _SESSION中或单独查询每个页面

时间:2012-06-20 15:23:10

标签: php sql pagination

想象一下,我有一个包含大量数据的数据库,用户可以从中搜索 典型搜索的结果通常是大约20-100行,然后进行分页(每页20行)。

我已经想过两种方法来处理这些页面的导航,并想知道这些页面是否有任何优点和/或缺点,以及是否有更好的选择。

  1. 查询一次,将结果存储在$_SESSION变量中,并根据当前页面过滤行。我想出这个的原因是为了使数据检索一次,而不必为用户导航的每个页面连接到数据库。我不知道它是否比我提出的另一种选择更好或更差。

    session_start();
    
    $search = rawurldecode($_GET['search']);   //search word
    $interval = rawurldecode($_GET['interval']); //rows per page
    $page = rawurldecode($_GET['page']);    //page
    
    $min_row = $interval * ($page-1)+1;
    $max_row = $interval * $page;
    
    //query if (no results stored or first page) && the current search is not the previous search                               
    if((empty($_SESSION['SEARCH_RESULTS']) || $page == 1) && $_SESSION['SEARCH_RESULTS']['TERM'] != $search){
        $_SESSION['SEARCH_RESULTS'] = array();
        $_SESSION['SEARCH_RESULTS']['TERM'] = $search;
    
        $query = "exec usp_Search '$search'";
    
        $dbh = new DBH;
        $dbh->Connect()->Query($query);
    
        while($row = $dbh->Fetch_Array()){  
            $_SESSION['SEARCH_RESULTS']['ROWS'][] = $row;                           
        }
    }
    
    for($j = 0; $j < count($_SESSION['SEARCH_RESULTS']['ROWS']); $j++){
        $row = $_SESSION['SEARCH_RESULTS']['ROWS'][$j];
    
        //ignore all other rows not on the page
        if($j < ($min_row-1) || $j > $max_row) continue; 
    
        //print stuff
    }
    
  2. 逐页查询。查询和分页非常简单。

    //Query
    $search = rawurldecode($_GET['search']);
    $interval = rawurldecode($_GET['interval']);
    $page = rawurldecode($_GET['page']);
    
    $min_row = $interval * ($page-1)+1;
    $max_row = $interval * $page;
    
    $query = "exec usp_Search '$search', $min_row, $max_row";
    
    $dbh = new DBH;
    $dbh->Connect()->Query($query);
    
    while($row = $dbh->Fetch_Array()){ 
        //print stuff                       
    }
    

  3. 替代方案中的SQL过程

    1. 只是一个带有SELECT查询的过程

      SELECT 
          COL1,
          COL2,
          COL...
      FROM TABLE1
      WHERE (
          COL1 LIKE '%'+@search+'%' OR 
          COL2 LIKE '%'+@search+'%' OR 
          COL... LIKE '%'+@search+'%'
      )
      
    2. 是一个创建临时表,然后从变量开始到结束选择行的过程。

      SELECT 
          COL1,
          COL2,
          COL...,
          ROW_NUMBER() OVER (ORDER BY COL1) AS [ROW_NUMBER]
      INTO #result
      FROM TABLE1
      WHERE (
          COL1 LIKE '%'+@search+'%' OR 
          COL2 LIKE '%'+@search+'%' OR 
          COL... LIKE '%'+@search+'%'
      )   
      
      SELECT 
          COL1,
          COL2,
          COL...
      FROM #result
      WHERE ROW_NUMBER BETWEEN @row_start AND @row_end
      

2 个答案:

答案 0 :(得分:0)

至少有几个原因,你真的无法将所有结果存储在_SESSION中:

  • 用户可以同时进行多次搜索
  • 搜索结果可能会在用户的网页加载之间发生变化。

第二点取决于您更新数据库的频率,但需要考虑。第一个是主要的,但是如果你以一种聪明的方式存储会话,你也可以绕过它(但你不希望_SESSION变得太大)。这与表现无关。

关于立即获取所有结果并存储到_SESSION的另一个考虑因素是,大多数用户每次访问时只能发出一个搜索请求。我知道你会认为他们总是会看到所有100个结果,但是如果这些结果的大部分甚至没有被使用,那么你只是为了保存一两个查询而浪费了很多。您可以自行决定用户的导航方式。


在阅读之后,这只会被20-30人使用,而且每天只有70行,我很满意地说你现在正在浪费时间来提高性能。如果发生重大变化,请查看以后更容易更新的代码。

答案 1 :(得分:0)

考虑这种情况:

  • 用户搜索存储在数据库中的100个结果的术语。
  • 获取所有100个结果后,您将查询数据库并将其存储在会话中。
  • 用户在前5个结果中找到他要查找的内容并离开搜索页面。

最后,你“过热”了数据库,无需获取95行。如果那100个结果是1000或10.000?

怎么办?

在我看来,在单个查询中获取所有结果并将结果存储在会话中是降低性能的“可靠方法”。