前言
分頁的sql優化是日常開發中經常遇到的問題,筆者在此做乙個經驗總結,並附上相應的實驗過程。
實驗準備
若不想親自實驗的,可以直接跳過這一節。但還是建議大家做一下實驗,眼見為實。
1.安裝測試資料庫
本次實驗使用的資料是mysql官方提供的employee資料庫,mysql官方提供了一些測試資料庫,可以在這裡找到
2.修改測試資料庫
安裝好employee資料庫後,筆者出於測試修改了一下salaries表的結構,方便測試,修改操作如下:
//修改原表的主鍵為id
create table `test_salaries` (
`id` int(11) not null auto_increment,
`emp_no` int(11) not null,
`salary` int(11) not null,
`from_date` date not null,
`to_date` date not null,
primary key (`id`),
constraint `test_salaries_ibfk_1` foreign key (`emp_no`) references `employees` (`emp_no`) on delete cascade
) engine=innodb default charset=latin1;
//匯入原表資料
insert into test_salaries (id,emp_no,salary,from_date,to_date) select null,emp_no,salary,from_date,to_date from salaries;
3.完成測試環境
至此,實驗的準備工作完成。可先檢視一下test_salaries表中有多少資料(以下測試基於該錶)
優化分頁sql查詢
優化分頁sql查詢的思路:
盡可能使用索引覆蓋掃瞄,而不是查詢所有的列。然後根據需要做一次關聯操作再返回所需的列(延遲關聯)
將limit查詢轉換為已知位置的查詢,讓mysql通過範圍掃瞄獲得對應的結果(範圍掃瞄)
延遲關聯
原始sql查詢語句:
select * from test_salaries where salary <= 94000 limit 2677500,10;
原始sql查詢語句執行效果:
只查詢id的sql語句:
select id from test_salaries where salary <= 94000 limit 2677500,10;
只查詢id的sql語句執行效果:
優化後的sql語句:
select * from test_salaries inner join (select id from test_salaries where salary <= 94000 limit 2677500,10) as lim using(id);
優化後的sql語句執行效果:
並且我們可以注意到,這條語句的執行時間與上一條只查詢id的語句的執行時間非常接近。
範圍掃瞄
原始sql查詢語句:
select * from test_salaries limit 2844030,10;
原始sql查詢語句執行效果:
只查詢id的sql語句:
select id from test_salaries order by id limit 2844030,1;
只查詢id的sql語句執行效果:
優化後的sql語句:
select * from test_salaries where id>=(select id from test_salaries order by id limit 2844030,1) limit 0,10;
優化後的sql語句執行效果:
同樣的,我們可以發現後兩句sql的執行時間比較接近。
應用程式層面的分頁優化設計
除了對sql語句進行優化,我們還可以在應用程式層面對分頁進行一些優化設計。
先獲取並快取較多的資料(例如1000條),然後每次分頁都從快取中獲取。這樣做可以讓應用程式根據結果集的大小採取不同策略,如果結果集少於1000,就可以在頁面上顯示所有的分頁連線;如果結果集大於1000,則可以在頁面上設計乙個額外的「找到的結果多於1000條」之類的按鈕。
mysql的分頁優化 mysql分頁優化
有個200多萬的使用者表,顯示列表時非常慢,查了一下原來使用了limit進行分頁。前幾頁用時很少 但是後面頁數就簡直不可忍了,實際的業務邏輯還有排序,就更慢了 試試用查詢時用帶索引的鍵來確定範圍。最大的id是103948598 時間和用limit比相差幾千倍啊!使用explain 檢視一下 mysq...
mysql 分頁優化 Mysql 查詢分頁優化
全表掃瞄,速度極慢 limit 語句的查詢時間與起始記錄的位置成正比 mysql 的 limit 語句是很方便,但是對記錄很多的表並不適合直接使用 建立測試表 drop table if exists t user create table test t user id int 10 unsigne...
mysql巢狀分頁 MySQL分頁優化
最近,幫同事重寫了乙個mysql sql語句,該sql語句涉及兩張表,其中一張表是字典表 需返回乙個字段 另一張表是業務表 本身就有150個字段,需全部返回 當然,欄位的個數是否合理在這裡不予評價。平時,返回的資料大概5w左右,系統尚能收到資料。但12月31日那天,資料量大概20w,導致sql執行時...