亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Mysql使用函數(shù)后不走索引怎么優(yōu)化

 更新時(shí)間:2023年08月14日 10:35:09   作者:怪?咖@  
當(dāng)在MySQL中使用函數(shù)時(shí),可能會(huì)導(dǎo)致查詢(xún)不走索引,從而影響性能,本文就介紹一下Mysql使用函數(shù)后不走索引怎么優(yōu)化,感興趣的可以了解一下

網(wǎng)上很多人說(shuō)mysql一旦使用函數(shù)就不走函數(shù),但是事實(shí)真的是如此嗎?我先說(shuō)明,并不是如此的,本篇文章會(huì)通過(guò) DAYOFWEEK() substr() 兩個(gè)函數(shù)作為條件查詢(xún),看看究竟是否會(huì)走索引(其他函數(shù)同理),使用函數(shù)不走索引的時(shí)候又應(yīng)該如何做sql優(yōu)化,本篇文章重點(diǎn)是基于這兩點(diǎn)進(jìn)行分析。

一、什么場(chǎng)景下使用函數(shù)索引會(huì)失效?

測(cè)試數(shù)據(jù)如下:

create_time和name列是都建立了索引的。

DROP TABLE IF EXISTS `demo`;
CREATE TABLE `demo`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `create_time` datetime NULL DEFAULT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `create_time`(`create_time`) USING BTREE,
  INDEX `name`(`name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;
INSERT INTO `demo` VALUES (1, '2023-04-28 10:41:16', 'zhangsan');
INSERT INTO `demo` VALUES (2, '2023-04-01 10:41:22', 'lisi');

DAYOFWEEK() :函數(shù)返回日期的工作日索引值,即星期日為1,星期一為2,星期六為7。 這些索引值對(duì)應(yīng)于ODBC標(biāo)準(zhǔn)。

通過(guò)下面會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題,假如是 select * 的情況下是不會(huì)走索引的,假如是只返回使用函數(shù)的列是會(huì)走索引的。

EXPLAIN SELECT * from  demo WHERE dayofweek(create_time) = 6 \G;
EXPLAIN SELECT dayofweek(create_time),create_time from  demo WHERE dayofweek(create_time) = 6 \G;

關(guān)于執(zhí)行計(jì)劃的解讀:

截取字符串語(yǔ)法: substr(obj,start,length)

參數(shù):

  • obj:從哪個(gè)內(nèi)容中截取,可以是數(shù)值或字符串。
  • start:從哪個(gè)字符開(kāi)始截取(1開(kāi)始,而不是0開(kāi)始)
  • length:截取幾個(gè)字符(空格也算一個(gè)字符)。

通過(guò)下面案例會(huì)發(fā)現(xiàn),跟上面的案例是一樣的,同樣是 select * 的情況下是不會(huì)走索引的。

EXPLAIN SELECT *  from demo WHERE substr(name,1,3) = 'lis'\G;
EXPLAIN SELECT substr(name,1,3),name,id  from demo WHERE substr(name,1,3) = 'lis'\G;

二、索引失效了應(yīng)該怎么處理?

1.通過(guò)【sql優(yōu)化】讓索引生效

那么問(wèn)題來(lái)了遇到這種查詢(xún)所有數(shù)據(jù)使用函數(shù)不走索引的我們應(yīng)該如何優(yōu)化。通過(guò)以下試驗(yàn)發(fā)現(xiàn)可以攜帶id,id是主鍵的情況下不會(huì)導(dǎo)致索引失效!

EXPLAIN SELECT substr(name,1,3),name,id,create_time  from demo WHERE substr(name,1,3) = 'lis'\G;
EXPLAIN SELECT substr(name,1,3),name,id  from demo WHERE substr(name,1,3) = 'lis'\G;

通過(guò)以下試驗(yàn)得出結(jié)論,假如使用函數(shù)作為條件查詢(xún),只能返回條件的那一列跟id主鍵列,一旦返回其他的列就會(huì)索引失效!

由此優(yōu)化方案便出來(lái)了,假設(shè)我們要查name列當(dāng)中前三個(gè)字母是lis的全行數(shù)據(jù),然后我們想讓他使用到索引,可以使用嵌套查詢(xún)的方案:

這里進(jìn)行提示以下:MySQL的 IN 運(yùn)算符可以使用索引,但是,有一點(diǎn)需要注意。如果你的IN子句中包含的值很多,那么MySQL可能會(huì)選擇不使用索引,因?yàn)閽呙璐罅康闹悼赡鼙仁褂盟饕?。這個(gè)閾值通常是1000個(gè)值,但這個(gè)值是可配置的。表內(nèi)數(shù)據(jù)太少使用 IN 也不會(huì)使用索引!

EXPLAIN SELECT * FROM demo WHERE id in (SELECT id  from demo WHERE substr(name,1,3) = 'lis') \G;

如下案例顯示實(shí)際上并未使用到索引

上面測(cè)試的表當(dāng)中就兩條數(shù)據(jù)所以顯示的in并沒(méi)有使用索引,如下表內(nèi)共有一萬(wàn)條數(shù)據(jù),然后對(duì)主鍵使用in查詢(xún),可以很明顯的看到,是使用了索引的。由此可證明in是會(huì)使用索引的,只不過(guò)mysql會(huì)根據(jù)權(quán)衡利弊到底使用索引快還是不使用索引快。

2.通過(guò)【虛擬列】讓索引生效

Mysql 5.7 中推出了一個(gè)非常實(shí)用的功能 虛擬列 Generated (Virtual) Columns

  • InnoDB支持在虛擬生成的列上建立二級(jí)索引。不支持其他索引類(lèi)型(主鍵索引)。在虛擬列上定義的二級(jí)索引有時(shí)也稱(chēng)為“虛擬索引”。
  • 二級(jí)索引可以在一個(gè)或多個(gè)虛擬列上創(chuàng)建,也可以在虛擬列與常規(guī)列或存儲(chǔ)生成列的組合上創(chuàng)建。包含虛擬列的二級(jí)索引可以定義為UNIQUE。
  • 當(dāng)在虛擬列上使用輔助索引時(shí),由于在INSERT和UPDATE操作期間在輔助索引(輔助又叫二級(jí)索引)記錄中實(shí)現(xiàn)虛擬列值時(shí)執(zhí)行計(jì)算,因此需要考慮額外的寫(xiě)成本。即使有額外的寫(xiě)成本,虛擬列上的二級(jí)索引也可能比生成的存儲(chǔ)列更可取,生成的存儲(chǔ)列在集群索引中具體化,從而導(dǎo)致需要更多磁盤(pán)空間和內(nèi)存的更大的表。如果沒(méi)有在虛擬列上定義二級(jí)索引,則會(huì)產(chǎn)生額外的讀取成本,因?yàn)槊看螜z查列的行時(shí)都必須計(jì)算虛擬列值。

語(yǔ)法: ALTER TABLE 表名稱(chēng) add column 虛擬列名稱(chēng) 虛擬列類(lèi)型 GENERATED ALWAYS as (表達(dá)式) [VIRTUAL | STORED];

MySQL 在處理 虛擬列存儲(chǔ)問(wèn)題的時(shí)候有兩種方式:

  • VIRTUAL(默認(rèn)):不存儲(chǔ)列值,在讀取表的時(shí)候自動(dòng)計(jì)算并返回,不消耗任何存儲(chǔ),這種存儲(chǔ)方式僅 InnoDB 支持設(shè)置索引。
  • STORED:在插入或更新時(shí)計(jì)算存儲(chǔ)列值,存儲(chǔ)的虛擬列需要存儲(chǔ)空間,并且 MyISAM 也可以設(shè)置索引。

下面我們基于 substr(name,1,3) 函數(shù)來(lái)創(chuàng)建一個(gè)虛擬列:

ALTER TABLE demo add column virtual_name VARCHAR(5) GENERATED ALWAYS as (substr(name,1,3)) VIRTUAL;

對(duì)虛擬列添加索引:

ALTER TABLE `demo`.`demo` 
ADD INDEX `virtual_name`(`virtual_name`) USING BTREE;

這時(shí)候就可以直接通過(guò)虛擬列來(lái)完成查詢(xún)操作了

 EXPLAIN SELECT *  from demo WHERE virtual_name = 'lis';

三、總結(jié)

假如使用函數(shù)作為條件查詢(xún),只能返回條件的那一列跟id主鍵列,一旦返回其他的列就會(huì)索引失效!針對(duì)于使用函數(shù)索引失效問(wèn)題,可以使用嵌套查詢(xún)來(lái)解決,也可以使用虛擬列來(lái)解決!

到此這篇關(guān)于Mysql使用函數(shù)后不走索引怎么優(yōu)化的文章就介紹到這了,更多相關(guān)Mysql函數(shù)不走索引優(yōu)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • mysql備份腳本 mysqldump使用方法詳解

    mysql備份腳本 mysqldump使用方法詳解

    這篇文章主要為大家詳細(xì)介紹了mysql備份腳本(mysqldump),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • MySQL修改root密碼的4種方法(小結(jié))

    MySQL修改root密碼的4種方法(小結(jié))

    這篇文章主要介紹了MySQL修改root密碼的4種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 淺談mysql的索引設(shè)計(jì)原則以及常見(jiàn)索引的區(qū)別

    淺談mysql的索引設(shè)計(jì)原則以及常見(jiàn)索引的區(qū)別

    下面小編就為大家?guī)?lái)一篇淺談mysql的索引設(shè)計(jì)原則以及常見(jiàn)索引的區(qū)別。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • Mysql用戶(hù)權(quán)限分配實(shí)戰(zhàn)項(xiàng)目詳解

    Mysql用戶(hù)權(quán)限分配實(shí)戰(zhàn)項(xiàng)目詳解

    用戶(hù)是數(shù)據(jù)庫(kù)的使用者和管理者,MySQL通過(guò)用戶(hù)的設(shè)置來(lái)控制數(shù)據(jù)庫(kù)操作人員的訪問(wèn)與操作范圍,這篇文章主要給大家介紹了關(guān)于Mysql用戶(hù)權(quán)限分配實(shí)戰(zhàn)項(xiàng)目的相關(guān)資料,需要的朋友可以參考下
    2023-12-12
  • MySQL中增量備份的幾種實(shí)現(xiàn)方法

    MySQL中增量備份的幾種實(shí)現(xiàn)方法

    MySQL數(shù)據(jù)庫(kù)的增量備份是確保數(shù)據(jù)安全和可恢復(fù)性的關(guān)鍵策略,本文就來(lái)介紹一下如何實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-01-01
  • 詳解MySQL如何有效的存儲(chǔ)IP地址及字符串IP和數(shù)值之間如何轉(zhuǎn)換

    詳解MySQL如何有效的存儲(chǔ)IP地址及字符串IP和數(shù)值之間如何轉(zhuǎn)換

    本文主要介紹了MySQL如何有效的存儲(chǔ)IP地址及字符串IP和數(shù)值之間如何轉(zhuǎn)換,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Windows下MySQL5.7.18安裝教程

    Windows下MySQL5.7.18安裝教程

    這篇文章主要為大家詳細(xì)介紹了Windows下MySQL5.7.18安裝教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Linux上通過(guò)binlog文件恢復(fù)mysql數(shù)據(jù)庫(kù)詳細(xì)步驟

    Linux上通過(guò)binlog文件恢復(fù)mysql數(shù)據(jù)庫(kù)詳細(xì)步驟

    binglog文件是服務(wù)器的二進(jìn)制日志記錄著該數(shù)據(jù)庫(kù)的所有增刪改的操作日志,接下來(lái)通過(guò)本文給大家介紹linux上通過(guò)binlog文件恢復(fù)mysql數(shù)據(jù)庫(kù)詳細(xì)步驟,非常不錯(cuò),需要的朋友參考下
    2016-08-08
  • win8.1安裝mysql5.6時(shí)遇到問(wèn)題解決方案

    win8.1安裝mysql5.6時(shí)遇到問(wèn)題解決方案

    本文主要記錄的是作者在win8.1安裝mysql5.6時(shí)遇到問(wèn)題的解決方案,網(wǎng)上查了很多方法都沒(méi)能解決,這里把最后的方法分享給大家
    2016-10-10
  • win2003 安裝2個(gè)mysql實(shí)例做主從同步服務(wù)配置

    win2003 安裝2個(gè)mysql實(shí)例做主從同步服務(wù)配置

    注意的就是路徑的正確書(shū)寫(xiě)。然后在my.ini的配置中,server_id必須保持唯一性。port避免使用3306,服務(wù)名稱(chēng)和mysql5.1不一樣即可。
    2011-05-05

最新評(píng)論