优化sql查询分页

时间:2013-12-06 04:01:57

标签: mysql sql wordpress wordpress-plugin

我可以做些什么来使我的代码更快地进行分页。?
我试着把它放在临时表中。 问题是创建临时表花了4.56秒。 wp_bp_xprofile_data中的行数仅为25k。我不知道为什么这需要花费很多时间。

此时我何时知道连接何时关闭。是每个页面刷新吗?

//
            //all variable are processed here....
            //

    $sql = "SELECT
          DN.User_ID,
          case when (FN.user_id is null or (length( trim( FN.meta_value )) = 0)) 
               and  (LN.user_id is null or (length( trim( LN.meta_value )) = 0)) then DN.value  
               else trim(concat( FN.meta_value, ' ', LN.meta_value )) end as Name,
          DN.Value DisplayName, 
          COALESCE( G.Value, '' ) Gender,
          COALESCE( BD.Value, '' ) Birthday,
          COALESCE( FLOOR( DATEDIFF( CURRENT_DATE, STR_TO_DATE( BD.value,'%m/%d/%Y'))/365), '' ) Age,
          COALESCE( P.Value, '' ) Phone,
          COALESCE( E.Value, '' ) Email,
          COALESCE( O.Value, '' ) Occupation, 
          COALESCE( R.Value, '' ) Region,
          COALESCE( PR.Value, '' ) Province,
          COALESCE( C.Value, '' ) City,
          COALESCE( CC.Value, '' ) CurrentCountry  
    FROM wp_bp_xprofile_data DN 
             LEFT JOIN wp_bp_xprofile_data G 
                ON DN.User_ID = G.User_ID AND G.field_id = 270 
             LEFT JOIN wp_bp_xprofile_data BD 
                ON DN.User_ID = BD.User_ID AND BD.field_id = 274 
             LEFT JOIN wp_bp_xprofile_data P 
                ON DN.User_ID = P.User_ID AND P.field_id = 275 
             LEFT JOIN wp_bp_xprofile_data E 
                ON DN.User_ID = E.User_ID AND E.field_id = 286 
             LEFT JOIN wp_bp_xprofile_data O 
                ON DN.User_ID = O.User_ID AND O.field_id = 71 
             LEFT JOIN wp_bp_xprofile_data CC
                ON DN.User_ID = CC.User_ID AND CC.field_id = 73 
             LEFT JOIN wp_bp_xprofile_data R
                ON DN.User_ID = R.User_ID AND R.field_id = 24 
             LEFT JOIN wp_bp_xprofile_data PR
                ON DN.User_ID = PR.User_ID AND PR.field_id = 355 
             LEFT JOIN wp_bp_xprofile_data C
                ON DN.User_ID = C.User_ID AND C.field_id = 354
             LEFT JOIN wp_usermeta FN
                ON DN.User_ID = FN.User_ID AND FN.meta_key = 'first_name'
             LEFT JOIN wp_usermeta LN
                ON DN.User_ID = LN.User_ID AND LN.meta_key = 'last_name'
    where DN.field_id = 1  ";

    if(!empty($_region))
    {
        $sql .= " AND R.User_ID IS NOT NULL AND R.Value = '".$_region."' ";
    }
    if(!empty($_province))
    {
        $sql .= " AND PR.User_ID IS NOT NULL AND PR.Value LIKE '".$_province."%' ";
    }
    if(!empty($_city))
    { 
        $sql .= " AND C.user_id IS NOT NULL AND C.Value LIKE '".$_city."%' ";
    }
    if(!empty($_ageMin) && !empty($_ageMax))
    {
        $sql .= " AND BD.User_ID IS NOT NULL AND FLOOR( DATEDIFF( CURRENT_DATE, STR_TO_DATE( BD.value,'%m/%d/%Y'))/365) BETWEEN   ".$_ageMin."  AND  ".$_ageMax;
    }
    if(!empty($_occupation))
    { 
        $sql .= " AND O.User_ID  IS NOT NULL AND O.Value = '".$_occupation."' ";
    }
    if(!empty($_gender))
    { 
        $sql .= " AND G.User_ID IS NOT NULL AND G.Value = '".$_gender."' ";
    } 
    if(!empty($_country))
    { 
        $sql .= " AND CC.User_ID IS NOT NULL AND CC.Value = '".$_country."' ";
    }  

    if(isset($search_val)){
        $sql .= "  
            AND
            (FN.meta_value LIKE '%".$search_val."%' OR  
            LN.meta_value LIKE '%".$search_val."%' OR 
            E.Value LIKE '%".$search_val."%' OR 
            O.Value LIKE '%".$search_val."%' OR 
            R.Value LIKE '%".$search_val."%' OR
            PR.Value LIKE '%".$search_val."%' OR
            C.Value LIKE '%".$search_val."%' OR
            CC.Value LIKE '%".$search_val."%')
        ";
    }

    $maxRow = $wpdb->getResults($sql);
    $limit = 30;
    $maxPage = ceil($maxRow/$limit); 

    if(!empty($page)){
        $start = ($limit * $page) - $limit; 
    }else{
        $start = 0; 
    }

    Generate_Pagination($maxRow);

    $sql .= " LIMIT ".$start." , ".$limit; 

    $datas = $wpdb->getResults($sql);

    foreach($data as $data){
        //output data;
    }
    ?>

使用Explain

enter image description here

删除此代码时

  

FN.meta_value LIKE'%“。$ search_val。”%'或
       LN.meta_value LIKE'%“。$ search_val。”%'或

会加快查询速度。 wp_usermeta有300k行。 也有不同的meta_key

wp_usermeta

     ` umeta_id | user_id | meta_key | meta_value`

3 个答案:

答案 0 :(得分:1)

尝试使用SQL_CALC_FOUND_ROWS

    $sql = 'SELECT SQL_CALC_FOUND_ROWS ... LIMIT ' . $limit;

    $rows = $this->_db->fetchAll($sql);                                                                    
    $data = array(                                                                                         
        "total" => $this->_db->fetchOne('SELECT FOUND_ROWS()'),             
        "rows" => $rows                                                                                    
    );  

答案 1 :(得分:0)

我注意到你正在发布

 $maxRow = $wpdb->getResults($sql);
在使用LIMIT附加OFFSET之前

。这将导致获取比分页所需的记录多得多的记录。

您正在发布此

$datas = $wpdb->getResults($sql);
附上LIMIT之后

,这很好。

您应该取消第一次getResults来电,并且您的表现会有所改善。

答案 2 :(得分:0)

您的主要问题是搜索。

您使用'%...%'来阻止使用简单索引。这意味着必须检查整个表格。有些数据库系统能够为此类搜索建立索引(Postgresql具有这样的功能),但您需要一些非常先进的设置才能使其快速工作。

http://www.postgresql.org/docs/8.3/static/textsearch-debugging.html

MySQL可能有相同的东西。

这就是说,在大多数情况下,您可以通过在WHERE子句中放置不首先使用'%...'的测试来减少行集。看起来你已经这么做了,但我没有详细说明:例如,如果你在不同的表中使用模式,那么WHERE仍然会很慢。

此外,所有那些出现在'%...'之前的测试应该是针对具有索引的列,如果你想要在执行SELECT时获得速度(在索引和做很多事情之间需要权衡) INSERT INTO而不是很多SELECT。)