3

想象一下,我有一个包含大量数据的数据库,用户可以从中进行搜索。
典型搜索的结果一般在 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                       
    }
    

备选方案中的 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
    
4

2 回答 2

0

考虑这种情况:

  • 用户搜索存储在数据库中的 100 个结果的术语。
  • 一旦获得所有 100 个结果,您就查询数据库并将它们存储在会话中。
  • 用户在前 5 个结果中找到他正在寻找的内容并离开搜索页面。

最后,您“过热”数据库以获取 95 行而一无所获。如果这 100 个结果是 1000 或 10.000 怎么办?

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

于 2012-06-20T16:40:04.243 回答
0

您真的不能将所有结果存储在 中_SESSION,至少有几个原因:

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

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

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


在读到这只会被 20 到 30 人使用并且每天只有 70 行之后,我很高兴地说你现在正在浪费时间试图提高性能。如果发生重大更改,请选择以后更容易更新的代码。

于 2012-06-20T15:46:20.210 回答