国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > PHP > 正文

Mysql中分頁查詢的兩個解決方法比較

2024-05-04 23:07:47
字體:
供稿:網(wǎng)友

mysql中分頁查詢有兩種方式, 一種是使用COUNT(*)的方式,具體代碼如下

復(fù)制代碼 代碼如下:


SELECT COUNT(*) FROM foo WHERE b = 1;
SELECT a FROM foo WHERE b = 1 LIMIT 100,10;


另外一種是使用SQL_CALC_FOUND_ROWS

復(fù)制代碼 代碼如下:


SELECT SQL_CALC_FOUND_ROWS a FROM foo WHERE b = 1 LIMIT 100, 10;
SELECT FOUND_ROWS();


第二種方式調(diào)用SQL_CALC_FOUND_ROWS之后會將WHERE語句查詢的行數(shù)放在FOUND_ROWS()之中,第二次只需要查詢FOUND_ROWS()就可以查出有多少行了。


討論這兩種方法的優(yōu)缺點:
首先原子性講,第二種肯定比第一種好。第二種能保證查詢語句的原子性,第一種當兩個請求之間有額外的操作修改了表的時候,結(jié)果就自然是不準確的了。而第二種則不會。但是非??上В话沩撁嫘枰M行分頁顯示的時候,往往并不要求分頁的結(jié)果非常準確。即分頁返回的total總數(shù)大1或者小1都是無所謂的。所以其實原子性不是我們分頁關(guān)注的重點。

下面看效率。這個非常重要,分頁操作在每個網(wǎng)站上的使用都是非常大的,查詢量自然也很大。由于無論哪種,分頁操作必然會有兩次sql查詢,于是就有很多很多關(guān)于兩種查詢性能的比較:

SQL_CALC_FOUND_ROWS真的很慢么?

To SQL_CALC_FOUND_ROWS or not to SQL_CALC_FOUND_ROWS?

老王這篇文章里面有提到一個covering index的概念,簡單來說就是怎樣才能只讓查詢根據(jù)索引返回結(jié)果,而不進行表查詢

具體看他的另外一篇文章:

MySQL之Covering Index

實驗
結(jié)合這幾篇文章,做的實驗:

表:

復(fù)制代碼 代碼如下:


CREATE TABLE IF NOT EXISTS `foo` (
`a` int(10) unsigned NOT NULL AUTO_INCREMENT,
`b` int(10) unsigned NOT NULL,
`c` varchar(100) NOT NULL,
PRIMARY KEY (`a`),
KEY `bar` (`b`,`a`)
) ENGINE=MyISAM;


注意下這里是使用b,a做了一個索引,所以查詢select * 的時候是不會用到covering index的,select a才會使用到covering index

復(fù)制代碼 代碼如下:


<?php

$host = '192.168.100.166';
$dbName = 'test';
$user = 'root';
$password = '';

$db = mysql_connect($host, $user, $password) or die('DB connect failed');
mysql_select_db($dbName, $db);


echo '==========================================' . "/r/n";

$start = microtime(true);
for ($i =0; $i<1000; $i++) {
mysql_query("SELECT SQL_NO_CACHE COUNT(*) FROM foo WHERE b = 1");
mysql_query("SELECT SQL_NO_CACHE a FROM foo WHERE b = 1 LIMIT 100,10");
}
$end = microtime(true);
echo $end - $start . "/r/n";

echo '==========================================' . "/r/n";

$start = microtime(true);
for ($i =0; $i<1000; $i++) {
mysql_query("SELECT SQL_NO_CACHE SQL_CALC_FOUND_ROWS a FROM foo WHERE b = 1 LIMIT 100, 10");
mysql_query("SELECT FOUND_ROWS()");
}
$end = microtime(true);
echo $end - $start . "/r/n";

echo '==========================================' . "/r/n";

$start = microtime(true);
for ($i =0; $i<1000; $i++) {
mysql_query("SELECT SQL_NO_CACHE COUNT(*) FROM foo WHERE b = 1");
mysql_query("SELECT SQL_NO_CACHE * FROM foo WHERE b = 1 LIMIT 100,10");
}
$end = microtime(true);
echo $end - $start . "/r/n";

echo '==========================================' . "/r/n";

$start = microtime(true);
for ($i =0; $i<1000; $i++) {
mysql_query("SELECT SQL_NO_CACHE SQL_CALC_FOUND_ROWS * FROM foo WHERE b = 1 LIMIT 100, 10");
mysql_query("SELECT FOUND_ROWS()");
}
$end = microtime(true);
echo $end - $start . "/r/n";


返回的結(jié)果:

Mysql中分頁查詢的兩個解決方法比較


和老王里面文章說的是一樣的。第四次查詢SQL_CALC_FOUND_ROWS由于不僅是沒有使用到covering index,也需要進行全表查詢,而第三次查詢COUNT(*),且select * 有使用到index,并沒進行全表查詢,所以有這么大的差別。

總結(jié)
PS: 另外提醒下,這里是使用MyISAM會出現(xiàn)三和四的查詢差別這么大,但是如果是使用InnoDB的話,就不會有這么大差別了。

所以我得出的結(jié)論是如果數(shù)據(jù)庫是InnoDB的話,我還是傾向于使用SQL_CALC_FOUND_ROWS

結(jié)論:SQL_CALC_FOUND_ROWS和COUNT(*)的性能在都使用covering index的情況下前者高,在沒使用covering index情況下后者性能高。所以使用的時候要注意這個。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 民县| 安塞县| 长阳| 四平市| 宜丰县| 宿迁市| 东乌珠穆沁旗| 晋江市| 盘锦市| 皋兰县| 长武县| 称多县| 宿迁市| 惠州市| 韩城市| 和田县| 应城市| 沿河| 白城市| 永川市| 高陵县| 石狮市| 磐安县| 汤阴县| 驻马店市| 宝鸡市| 垦利县| 绥棱县| 尚义县| 固安县| 玉溪市| 洞头县| 涞水县| 卫辉市| 墨竹工卡县| 沙坪坝区| 梁平县| 池州市| 苍溪县| 通许县| 泉州市|