MySQL分頁優化實驗與總結

前言

分頁的sql優化是平常開發中常常遇到的問題,筆者在此作一個經驗總結,並附上相應的實驗過程。html

實驗準備

若不想親自實驗的,能夠直接跳過這一節。但仍是建議你們作一下實驗,眼見爲實。mysql

1.安裝測試數據庫

本次實驗使用的數據是mysql官方提供的employee數據庫,mysql官方提供了一些測試數據庫,能夠在這裏找到https://dev.mysql.com/doc/ind...sql

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表中有多少數據(如下測試基於該表)緩存

SELECT count(*)FROM test_salaries;

test_salaries表大小.png

優化分頁SQL查詢

優化分頁SQL查詢的思路:測試

  1. 儘量使用索引覆蓋掃描,而不是查詢全部的列。而後根據須要作一次關聯操做再返回所需的列(延遲關聯)
  2. 將limit查詢轉換爲已知位置的查詢,讓mysql經過範圍掃描得到對應的結果(範圍掃描)

延遲關聯

原始sql查詢語句:優化

SELECT * FROM test_salaries WHERE salary <= 94000 LIMIT 2677500,10;

原始sql查詢語句執行效果:spa

原始sql查詢語句執行效果(延遲關聯).png

只查詢id的sql語句:設計

SELECT id FROM test_salaries WHERE salary <= 94000 LIMIT 2677500,10;

只查詢id的sql語句執行效果:code

只查詢id的sql語句執行效果(延遲關聯).png

優化後的sql語句:

SELECT * FROM test_salaries INNER JOIN (SELECT id FROM test_salaries WHERE salary <= 94000 LIMIT 2677500,10) AS lim USING(id);

優化後的sql語句執行效果:
優化後的sql語句執行效果(延遲關聯).png
而且咱們能夠注意到,這條語句的執行時間與上一條只查詢id的語句的執行時間很是接近。

範圍掃描

原始sql查詢語句:

SELECT * FROM test_salaries limit 2844030,10;

原始sql查詢語句執行效果:

原始sql查詢語句執行結果(範圍掃描).png

只查詢id的sql語句:

SELECT id FROM test_salaries ORDER BY id limit 2844030,1;

只查詢id的sql語句執行效果:
只查詢id的sql語句執行效果(範圍掃描).png

優化後的sql語句:

SELECT * FROM test_salaries WHERE id>=(SELECT id FROM test_salaries ORDER BY id limit 2844030,1) limit 0,10;

優化後的sql語句執行效果:

優化後的sql語句執行效果(範圍掃描).png

一樣的,咱們能夠發現後兩句sql的執行時間比較接近。

應用程序層面的分頁優化設計

除了對sql語句進行優化,咱們還能夠在應用程序層面對分頁進行一些優化設計。

  1. 將具體的頁數換成「下一頁」按鈕,假設每頁顯示20條記錄,那麼每次查詢時都是用LIMIT返回21條記錄並只顯示20條,若是第21條存在,那麼就顯示「下一頁」按鈕。
  2. 先獲取並緩存較多的數據(例如1000條),而後每次分頁都從緩存中獲取。這樣作可讓應用程序根據結果集的大小採起不一樣策略,若是結果集少於1000,就能夠在頁面上顯示全部的分頁鏈接;若是結果集大於1000,則能夠在頁面上設計一個額外的「找到的結果多於1000條」之類的按鈕。
相關文章
相關標籤/搜索