站長(zhǎng)資訊網(wǎng)
        最全最豐富的資訊網(wǎng)站

        ThinkPHP5水平分表后分頁(yè)查詢解決方案

        ThinkPHP5內(nèi)置了partition方法,可用于實(shí)現(xiàn)簡(jiǎn)單的分表。新增,修改,刪除,查詢單條數(shù)據(jù)時(shí),用partition方法都可以輕松搞定,因?yàn)檫@些操作有一個(gè)共同的特點(diǎn),就是能事先明確的知道,我要操作的是哪一條記錄。但有一個(gè)需求,ThinkPHP5似乎沒有解決,比如當(dāng)一個(gè)大表,被拆分成若干個(gè)子表時(shí),如何根據(jù)相關(guān)條件及排序獲取分頁(yè)數(shù)據(jù)。

        這種需求場(chǎng)景下,由于事先并不知道哪些數(shù)據(jù)會(huì)出現(xiàn)在第一頁(yè),哪些數(shù)據(jù)會(huì)出現(xiàn)在第二頁(yè),這些根據(jù)檢索條件動(dòng)態(tài)匹配的列表數(shù)據(jù),該如何查詢呢?

        一次失敗的嘗試

        最先想到的也是最直接的一種方式,就是將partition方法和paginate方法結(jié)合起來(lái),看似順理成章的事,結(jié)果悲劇了,數(shù)據(jù)庫(kù)被搞得直接奔潰。究其原因,要想實(shí)現(xiàn)分頁(yè)查詢,partition方法中需要union若干個(gè)子表,而且每個(gè)union的子表中,都是select * 的形式,這樣就會(huì)嚴(yán)重影響到查詢的效率,況且,在獲取記錄總數(shù)的時(shí)候,也完全沒必要查詢出所有字段。

        成功之道

        既然select * 會(huì)影響效率,那么select 出主鍵會(huì)怎樣呢?當(dāng)然是相當(dāng)?shù)目欤】傮w思路就是分兩次獲取數(shù)據(jù),第一次先查詢出主鍵,然后第二次,根據(jù)主鍵,獲取對(duì)應(yīng)的數(shù)據(jù)。具體實(shí)現(xiàn)如下:

        核心思想

        水平分表后,當(dāng)需要分頁(yè)獲取數(shù)據(jù)時(shí),效率會(huì)變得非常低下,拆分的子表越多,對(duì)查詢性能的影響就會(huì)越大。所以核心思想就是,盡量通過(guò)主鍵id來(lái)獲取對(duì)應(yīng)的數(shù)據(jù)記錄,也就是分兩次來(lái)獲取列表數(shù)據(jù)。

        1. 先查詢總記錄數(shù)及主鍵id

        該步驟中,union 子表的select語(yǔ)句中,只需要列出主鍵id和其它額外必須的字段即可,不相關(guān)的字段無(wú)需出現(xiàn)。

        2. 根據(jù)主鍵id查詢對(duì)應(yīng)的完整數(shù)據(jù)。

        函數(shù)封裝

        1. 構(gòu)造獲取總記錄數(shù)及主鍵ID的sql子查詢語(yǔ)句

        /**  * 構(gòu)造獲取總記錄數(shù)及主鍵ID的sql子查詢語(yǔ)句  * @param $table 主表名稱  * @param $idKey 主鍵id字段名稱  * @param string $fields 其它字段名稱,多個(gè)字段用英文逗號(hào)分隔  * @param int $num 子表數(shù)量  * @param string $where 查詢條件  * @return array  */ function buildPartitionSql($table,$idKey,$fields='',$num=1,$where='') {     $countTable = [];     $listTable = [];     $fieldList = [$idKey];     if ($fields) {         $fieldList = array_merge($fieldList,explode(',',$fields));         $fieldList = array_unique($fieldList);     }     $fieldStr = implode(',',$fieldList);     for ($i = 0; $i < $num; $i++) {         $countTable[] = sprintf('SELECT %s FROM %s_%s where 1=1 %s', $idKey, $table, ($i + 1), $where);         $listTable[] = sprintf('SELECT %s FROM %s_%s where 1=1 %s', $fieldStr,$table, ($i + 1), $where);     }     $countTable = '( ' . implode(" UNION ", $countTable) . ') AS ' . $table;     $listTable = '( ' . implode(" UNION ", $listTable) . ') AS ' . $table;     $tables = ['countSql' => $countTable, 'listSql' => $listTable];     return $tables; }

        調(diào)用方式:

        假設(shè)buildPartitionSql函數(shù)的執(zhí)行結(jié)果為$tables,那么完整的SQL語(yǔ)句如下:

        獲取總記錄數(shù)的完整sql:

        select count(1) as total from .$tables['countSql']

        獲取主鍵id的完整sql:

        select * from .$tables['listSql']. limit 0,10

        2. 構(gòu)造獲取指定id對(duì)應(yīng)記錄的sql子查詢語(yǔ)句

        /**  * 構(gòu)造獲取指定id對(duì)應(yīng)記錄的sql子查詢語(yǔ)句  * @param $table 主表名稱  * @param $idKey 指定的id字段名稱  * @param $idValues 指定的id字段值  * @param int $num 子表數(shù)量  * @return string  */ function buildPartitionListSql($table,$idKey,$idValues,$num=1) {     $sql = '';     $ids = is_array($idValues) ? implode(',',$idValues) : $idValues;     if ($ids) {         $listTable = [];         for ($i = 0; $i < $num; $i++) {             $listTable[] = sprintf('SELECT * FROM %s_%s where %s in (%s)', $table, ($i + 1), $idKey, $ids);         }         $sql = '( ' . implode(" UNION ", $listTable) . ') AS ' . $table;     }     return $sql; }

        調(diào)用方式:

        假設(shè)buildPartitionListSql函數(shù)的執(zhí)行結(jié)果為$sql,那么完整的SQL語(yǔ)句如下:

        select * from .$sql

        注意:業(yè)務(wù)層面的所有檢索條件,都放在了第一步的union子句中,第二步只需要根據(jù)id拿數(shù)據(jù)就行了。

        php中文網(wǎng),大量的免費(fèi)thinkphp入門教程,歡迎在線學(xué)習(xí)!

        贊(0)
        分享到: 更多 (0)
        網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
        主站蜘蛛池模板: 精品亚洲A∨无码一区二区三区| 国产午夜精品理论片| 国产精品久久波多野结衣| 国产精品一香蕉国产线看观看| 99久久99久久久精品齐齐| 亚洲性日韩精品一区二区三区| 高清日韩精品一区二区三区 | 国产精品中文字幕在线观看| 亚洲精品NV久久久久久久久久| 国产精品毛片一区二区| 精品国产一区二区三区久久| 精品欧洲av无码一区二区| 综合在线视频精品专区| 久久久久九国产精品| 国产欧美日韩综合精品一区二区三区| 国产精品国产三级专区第1集| 国产精品无码专区| 久久精品国产亚洲AV电影| 亚洲Av无码精品色午夜| 青青草97国产精品免费观看| 精品久久国产一区二区三区香蕉| 国产成人精品福利网站在线观看 | 国产精品99| 国产高清精品在线| 99国内精品久久久久久久| 久久精品视频网| 中文字幕亚洲精品资源网| 性色精品视频网站在线观看| 久久九九有精品国产23百花影院| 国产精品视频第一页| 国产精品青草久久久久婷婷 | 尤物yw午夜国产精品视频| 欧美精品亚洲精品日韩专区| 日韩在线精品一二三区| 四虎精品免费永久免费视频| 亚洲国产成人精品女人久久久| 亚欧洲精品在线视频免费观看| 四虎精品亚洲一区二区三区| 亚洲国产精品无码久久| 亚洲AV日韩精品久久久久| 久久精品欧美日韩精品|