最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL 使用自定義變量進(jìn)行查詢優(yōu)化

 更新時間:2021年05月14日 09:32:10   作者:島上碼農(nóng)  
MySQL自定義變量估計(jì)很少人有用到,但是如果用好了也是可以輔助進(jìn)行性能優(yōu)化的。需要注意的是變量是基于連接會話的,而且可能存在一些意外的情況,需要小心使用。本篇介紹如何利用自定義變量進(jìn)行查詢優(yōu)化,提高效率

優(yōu)化排序查詢

自定義變量的一個重要特性是你可以同時將該變量的數(shù)學(xué)計(jì)算后的結(jié)果再賦值給該變量,類似于我們的 i = i + 1這種方式。下面是一個用于計(jì)算數(shù)據(jù)表行號的例子:

SET @rownum := 0;
SELECT actor_id, @rownum := @rownum + 1 AS rownum
FROM sakila.actor LIMIT 3;

actor_id rownum
1 1
2 2
3 3

得到的結(jié)果也許看起來沒什么意義,這是因?yàn)橹麈I是從1自增的,因此行號和主鍵值是一樣的。但是,這種方式可以用于做排序。例如需要查詢飾演電影數(shù)量最多的前10名演員,通常的做法是像下面這樣寫:

SELECT actor_id, COUNT(*) as cnt
FROM sakila.film_actor
GROUP BY actor_id
ORDER BY cnt DESC
LIMIT 10;

得到的結(jié)果也許看起來沒什么意義,這是因?yàn)橹麈I是從1自增的,因此行號和主鍵值是一樣的。但是,這種方式可以用于做排序。例如需要查詢飾演電影數(shù)量最多的前10名演員,通常的做法是像下面這樣寫:

SELECT actor_id, COUNT(*) as cnt
FROM sakila.film_actor
GROUP BY actor_id
ORDER BY cnt DESC
LIMIT 10;

如果我們要獲得相應(yīng)的排名值的話,則可以引入變量來完成:

SET @curr_cnt := 0, @prev_cnt := 0, @rank := 0;
SELECT actor_id,
	@curr_cnt := cnt AS cnt,
  @rank 		:= IF(@prev_cnt <> @curr_cnt, @rank+1, @rank) as rank,
  @prev_cnt	:= @curr_cnt AS dummy
FROM (
  SELECT actor_id, COUNT(*) AS cnt
  FROM sakila.film_actor
	GROUP BY actor_id
	ORDER BY cnt DESC
	LIMIT 10
) as der;

這里是將飾演電影的數(shù)量賦值給了 curr_cnt 變量,使用了prev_cnt 存儲前一個演員的參演數(shù)量。排名從第一名開始的,如果后面的演員的數(shù)量和前一個演員的數(shù)量不同,則排名要往下(+1),如果相同則和前一個演員的排名相同。通過這種方式可以直接從查詢結(jié)果中得到演員的排名,而不需要再從數(shù)據(jù)庫查詢做二次處理(當(dāng)然也可以通過程序代碼實(shí)現(xiàn))。

避免重復(fù)獲取剛剛修改的數(shù)據(jù)行

如果想在更新數(shù)據(jù)行的時候再重新獲取數(shù)據(jù)行的信息,往往需要再讀取一次數(shù)據(jù)庫。這是因?yàn)?MySQL 不像 PostgreSQL 的 UPDATE RETURNING 功能可以同時返回更新后的數(shù)據(jù)行,而只是返回更新影響的行數(shù)。但是,我們可以通過自定義變量完成這樣的操作。例如,獲取剛剛被修改過更新時間的行,不使用自定義變量的話需要做一次額外的查詢:

UPDATE tb1 SET lastUpdated = NOW() WHERE id = 1;
SELECT lastUpdated FROM tb1 WHERE id = 1;

而使用自定義變量的時候可以避免這種情況:

UPDATE tb1 SET lastUpdated = NOW() WHERE id = 1 AND @now  := NOW();
SELECT @now;

雖然還是有一個查詢操作,但是后面的查詢操作不再需要訪問數(shù)據(jù)庫了。

懶加載的聯(lián)合查詢

假設(shè)我們需要寫一個聯(lián)合查詢完成如下任務(wù):在聯(lián)合的分支上查找匹配的數(shù)據(jù)行,如果找到了就跳過其他分支。y這種情況發(fā)生在需要從熱區(qū)數(shù)據(jù)或低頻訪問數(shù)據(jù)中查找(比如近期訂單和歷史訂單)。這是下面針對用戶查詢的一個普通的 SQL:

SELECT id FROM users WHERE  id = 123
UNION ALL
SELECT id FROM users_archived WHERE id = 123;

這個查詢會先從當(dāng)前正在使用的用戶表查詢 id 為123的用戶,然后 在從已歸檔的用戶表找同樣 id 的用戶。但是,這種寫法比較低效,即便是在 users 表找到了想要找的用戶,還是需要從users_archived 這個表再找一次,而實(shí)際用戶 id 為123的只會存在其中的一張表中或兩張表的數(shù)據(jù)是一樣的。通過懶加載的聯(lián)合查詢,可以避免這種情況——只有在第一個分支沒有找到數(shù)據(jù)時才進(jìn)行第二個分支的查詢。因此可以使用 MySQL 的 GREATEST 方法來作為查詢結(jié)果的容器以避免多返回?cái)?shù)據(jù)列。

SELECT GREATEST(@found := -1, id) AS id, users.name, 'users' as which_tb1
FROM users WHERE id = 123
UNION ALL
	SELECT id, users_archived.name, 'users_archived'
  FROM users_archived WHERE id = 123 AND @found IS NULL
UNION ALL
	SELECT 1, '', 'reset' FROM DUAL WHERE ( @found := NULL) IS NOT NULL;

上述的查詢?nèi)绻谝恍杏薪Y(jié)果,則@found 不會被賦值,因而是 NULL,從而執(zhí)行第二次查詢。而第三次的 UNION 實(shí)際沒什么效果,只是為了將@found恢復(fù)到 NULL 值,以便這段 SQL 可以重復(fù)執(zhí)行。另一個驗(yàn)證的方法是對同一張表進(jìn)行這樣的操作,可以發(fā)現(xiàn)實(shí)際只會返回一行數(shù)據(jù)或不返回?cái)?shù)據(jù)(查詢不到數(shù)據(jù)時)。

SELECT GREATEST(@found := -1, `id`) AS `id`, `infocenter_city`.`name`, 'city' as which_tb1 
FROM `infocenter_city` WHERE `id` = 460100 
UNION ALL 
	SELECT `id`, `infocenter_city`.`name`, 'infocenter_city' 
	FROM `infocenter_city` WHERE id = 460100 AND @found IS NULL 
UNION ALL 
	SELECT 1, '', 'reset' FROM DUAL WHERE ( @found := NULL) IS NOT NULL

以上就是MySQL 使用自定義變量進(jìn)行查詢優(yōu)化的詳細(xì)內(nèi)容,更多關(guān)于MySQL 用自定義變量進(jìn)行查詢優(yōu)化的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Linux下安裝mysql-5.6.12-linux-glibc2.5-x86_64.tar.gz

    Linux下安裝mysql-5.6.12-linux-glibc2.5-x86_64.tar.gz

    這篇文章主要介紹了Linux下安裝mysql-5.6.12-linux-glibc2.5-x86_64.tar.gz的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-09-09
  • 詳解MySQL中存儲函數(shù)創(chuàng)建與觸發(fā)器設(shè)置

    詳解MySQL中存儲函數(shù)創(chuàng)建與觸發(fā)器設(shè)置

    這篇文章主要為大家詳細(xì)介紹了MySQL中存儲函數(shù)的創(chuàng)建與觸發(fā)器的設(shè)置,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價值,需要的可以參考一下
    2022-08-08
  • 一文搞懂MySQL運(yùn)行機(jī)制原理

    一文搞懂MySQL運(yùn)行機(jī)制原理

    這篇文章主要介紹了一文搞懂MySQL運(yùn)行機(jī)制原理,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • mysql 分頁優(yōu)化解析

    mysql 分頁優(yōu)化解析

    似乎討論分頁的人很少,難道大家都沉迷于limit m,n?在有索引的情況下,limit m,n速度足夠,可是在復(fù)雜條件搜索時,where somthing order by somefield+somefieldmysql會搜遍數(shù)據(jù)庫,找出“所有”符合條件的記錄,然后取出m,n條記錄。
    2008-04-04
  • mysql 無限級分類實(shí)現(xiàn)思路

    mysql 無限級分類實(shí)現(xiàn)思路

    關(guān)于該問題,暫時自己還沒有深入研究,在網(wǎng)上找到幾種解決方案,各有優(yōu)缺點(diǎn)。
    2011-08-08
  • php下巧用select語句實(shí)現(xiàn)mysql分頁查詢

    php下巧用select語句實(shí)現(xiàn)mysql分頁查詢

    mysql分頁查詢是我們經(jīng)常見到的問題,那么應(yīng)該如何實(shí)現(xiàn)呢?下面就教您一個實(shí)現(xiàn)mysql分頁查詢的好方法,供您參考學(xué)習(xí)。
    2010-12-12
  • MySQL 日期格式化的使用示例

    MySQL 日期格式化的使用示例

    在MySQL中,可以使用DATE_FORMAT函數(shù)對日期進(jìn)行格式化,本文就來介紹一下MySQL 日期格式化的使用示例,具有一定的參考價值,感興趣的可以了解一下
    2023-10-10
  • MySQL每日一練項(xiàng)目之校園教務(wù)系統(tǒng)

    MySQL每日一練項(xiàng)目之校園教務(wù)系統(tǒng)

    這篇文章主要給大家介紹了關(guān)于MySQL每日一練項(xiàng)目之校園教務(wù)系統(tǒng)的相關(guān)資料,教務(wù)管理系統(tǒng)是一套高校專用管理系統(tǒng),主要用于解決信息化辦公流程、學(xué)生管理、課程管理、教職工管理等相關(guān)問題,需要的朋友可以參考下
    2023-09-09
  • Mac下mysql 8.0.22 找回密碼的方法

    Mac下mysql 8.0.22 找回密碼的方法

    這篇文章主要介紹了Mac下mysql 8.0.22 找回密碼的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • MySQL?根據(jù)表名稱生成完整select語句詳情

    MySQL?根據(jù)表名稱生成完整select語句詳情

    這篇文章主要介紹了MySQL?根據(jù)表名稱生成完整select語句,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-06-06

最新評論

张家港市| 利辛县| 墨竹工卡县| 泗水县| 昂仁县| 通榆县| 阿拉善左旗| 丰镇市| 疏勒县| 昭通市| 赤城县| 龙里县| 昭平县| 塔河县| 鸡西市| 武隆县| 卢龙县| 尼木县| 鲁甸县| 安义县| 眉山市| 丰台区| 子长县| 昭觉县| 莱阳市| 东至县| 营山县| 廉江市| 澳门| 永安市| 元谋县| 综艺| 崇义县| 马龙县| 香河县| 甘孜县| 周至县| 荥阳市| 蓝田县| 蚌埠市| 尖扎县|