欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文詳解MySQL JSON字段索引設(shè)置的具體方案

 更新時間:2025年09月14日 14:14:29   作者:JialBro  
在數(shù)據(jù)存儲需求日益靈活的今天,JSON憑借其無需預(yù)先定義結(jié)構(gòu)的特性,成為存儲非結(jié)構(gòu)化、半結(jié)構(gòu)化數(shù)據(jù)的理想選擇,MySQL雖提供了豐富的JSON讀寫函數(shù),但無法直接為整個JSON列建立索引,本文將以實際業(yè)務(wù)案例為基礎(chǔ),手把手教你實現(xiàn)JSON字段的高效索引

引言

在數(shù)據(jù)存儲需求日益靈活的今天,JSON憑借其無需預(yù)先定義結(jié)構(gòu)的特性,成為存儲非結(jié)構(gòu)化、半結(jié)構(gòu)化數(shù)據(jù)(如用戶行為日志、第三方API返回數(shù)據(jù)、動態(tài)配置信息)的理想選擇。MySQL自5.7.8版本起正式支持JSON數(shù)據(jù)類型,雖提供了豐富的JSON讀寫函數(shù),但無法直接為整個JSON列建立索引——這與支持廣義倒排索引(GIN)的數(shù)據(jù)庫不同。不過,MySQL提供了兩種間接索引JSON字段特定內(nèi)容的方案,可滿足絕大多數(shù)查詢場景。本文將以實際業(yè)務(wù)案例為基礎(chǔ),手把手教你實現(xiàn)JSON字段的高效索引。

一、背景與案例準(zhǔn)備

1.1 MySQL JSON索引的局限性

MySQL不支持GIN索引,無法對JSON文檔整體建立索引,但若業(yè)務(wù)中需頻繁根據(jù)JSON內(nèi)部某一關(guān)鍵字段(如用戶郵箱、訂單ID)查詢,直接使用JSON_EXTRACT等函數(shù)查詢會導(dǎo)致全表掃描,性能極差。此時,需通過“生成列”或“函數(shù)索引”間接索引JSON中的目標(biāo)字段。

1.2 案例表與JSON數(shù)據(jù)結(jié)構(gòu)

本文以“應(yīng)用操作日志表”activity_log為例,表結(jié)構(gòu)如下:

CREATE TABLE `activity_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `properties` json NOT NULL, -- 存儲JSON格式的日志詳情
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, -- 日志生成時間
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

properties字段中存儲的JSON數(shù)據(jù)結(jié)構(gòu)如下,我們的目標(biāo)是為request對象下的email字段建立索引,實現(xiàn)“快速查詢特定用戶提交的表單日志”:

{
  "uuid": "e7af5df8-f477-4b9b-b074-ad72fe17f502",
  "request": {
    "email": "little.bobby@tables.com",
    "firstName": "Little",
    "formType": "vehicle-inquiry",
    "lastName": "Bobby",
    "message": "Hello, can you tell me what the specs are for this vehicle?",
    "postcode": "75016",
    "townCity": "Dallas"
  }
}

二、方案一:基于生成列(Generated Column)索引JSON

2.1 什么是生成列?

生成列(也稱計算列、派生列)的值并非手動插入,而是由預(yù)先定義的表達式動態(tài)計算得出。該表達式需滿足兩個條件:

  • 定量性(Scalar):結(jié)果必須是單一值(如字符串、數(shù)字),不能是數(shù)組或?qū)ο螅?/li>
  • 確定性(Deterministic):相同輸入必須返回相同結(jié)果(如JSON_EXTRACT符合,NOW()不符合)。

對于JSON字段,生成列的核心作用是提取JSON中目標(biāo)字段的值并固化為普通列,再為該列建立常規(guī)索引。

2.2 步驟1:驗證JSON字段提取表達式

首先需確認(rèn)“提取JSON中request.email”的表達式是否正確,避免后續(xù)生成列數(shù)據(jù)錯誤。MySQL提供兩種常用的JSON解引用語法:

簡化語法:->>(等價于JSON_UNQUOTE(JSON_EXTRACT(...))

SELECT properties->>"$.request.email" AS extract_email 
FROM activity_log;

完整語法:JSON_UNQUOTE(JSON_EXTRACT(...))

SELECT JSON_UNQUOTE(JSON_EXTRACT(properties, "$.request.email")) AS extract_email 
FROM activity_log;

兩種語法執(zhí)行結(jié)果一致,均返回little.bobby@tables.com,說明表達式有效。

2.3 步驟2:創(chuàng)建生成列

確認(rèn)表達式無誤后,通過ALTER TABLE添加生成列,指定表達式為“提取JSON中request.email”:

ALTER TABLE activity_log 
ADD COLUMN request_email VARCHAR(255) -- 匹配email字段的長度需求
GENERATED ALWAYS AS (properties->>"$.request.email") -- 動態(tài)計算規(guī)則
STORED; -- 可選:STORED(物理存儲,查詢更快)/ VIRTUAL(邏輯計算,節(jié)省空間)
  • STORED vs VIRTUAL:若查詢頻繁,建議用STORED(需額外存儲空間);若存儲空間有限且查詢頻率低,可用VIRTUAL(MySQL 5.7默認(rèn))。

添加后可通過查詢驗證生成列:

SELECT id, request_email FROM activity_log;
-- 結(jié)果:id=1,request_email=little.bobby@tables.com

且MySQL會自動維護生成列——若properties中的email更新,request_email會同步變化。

2.4 步驟3:為生成列建立索引

生成列本質(zhì)是普通列,直接用ADD INDEX建立B樹索引即可:

ALTER TABLE activity_log 
ADD INDEX idx_json_request_email (request_email) USING BTREE;

2.5 驗證索引有效性

通過EXPLAIN查看查詢是否使用索引:

EXPLAIN 
SELECT * FROM activity_log 
WHERE request_email = 'little.bobby@tables.com';

執(zhí)行結(jié)果中,type列顯示refkey列顯示idx_json_request_email,說明索引已生效,避免了全表掃描。

2.6 優(yōu)化器的“穿透”能力

MySQL優(yōu)化器具備智能識別能力:即使查詢時直接使用JSON提取語法(而非生成列名),也能自動匹配生成列索引。例如:

EXPLAIN 
SELECT * FROM activity_log 
WHERE properties->>"$.request.email" = 'little.bobby@tables.com';

通過SHOW WARNINGS可查看優(yōu)化器改寫后的SQL,會發(fā)現(xiàn)查詢被自動轉(zhuǎn)化為“基于生成列request_email的過濾”,仍能使用索引。

三、方案二:基于函數(shù)索引(Functional Index)索引JSON

3.1 函數(shù)索引的適用場景

MySQL 8.0.13及以上版本支持函數(shù)索引(也稱表達式索引),可直接對“JSON字段提取表達式”建立索引,無需創(chuàng)建中間生成列,簡化操作流程。但需注意:JSON提取結(jié)果默認(rèn)是LONGTEXT類型,無法直接索引,需通過CAST轉(zhuǎn)換為可索引類型(如CHAR、VARCHAR)。

3.2 步驟1:創(chuàng)建函數(shù)索引

直接對“提取并轉(zhuǎn)換后的JSON字段”建立索引,同時顯式指定字符集排序規(guī)則(避免字符集不匹配錯誤):

ALTER TABLE activity_log 
ADD INDEX idx_json_email_func (
  CAST(properties->>"$.request.email" AS CHAR(255)) COLLATE utf8mb4_bin
) USING BTREE;
  • CAST轉(zhuǎn)換:將LONGTEXT轉(zhuǎn)為CHAR(255),長度需匹配業(yè)務(wù)中email的最大長度;
  • COLLATE utf8mb4_bin:顯式指定排序規(guī)則,避免因表默認(rèn)排序規(guī)則與JSON字段不一致導(dǎo)致的錯誤。

3.3 步驟2:驗證索引有效性

同樣用EXPLAIN驗證,查詢時需使用與索引表達式一致的語法(含CAST和排序規(guī)則):

EXPLAIN 
SELECT * FROM activity_log 
WHERE CAST(properties->>"$.request.email" AS CHAR(255)) COLLATE utf8mb4_bin = 'little.bobby@tables.com';

結(jié)果中key列顯示idx_json_email_func,說明索引生效。

四、兩種方案對比與選型建議

對比維度生成列方案(MySQL 5.7+)函數(shù)索引方案(MySQL 8.0.13+)
適用版本5.7及以上(兼容性更廣)8.0.13及以上(需高版本支持)
操作步驟需先創(chuàng)建生成列,再建索引(兩步)直接建索引(一步),流程更簡
存儲空間需額外存儲生成列(STORED模式)無需額外存儲,僅存儲索引
查詢靈活性支持直接用生成列名查詢,也支持JSON語法需嚴(yán)格匹配索引表達式(含CAST和排序規(guī)則)
維護成本需維護生成列(自動,無手動操作)無中間列,維護成本更低

選型建議:

  • 若使用MySQL 5.7:只能選擇生成列方案;
  • 若使用MySQL 8.0.13+:優(yōu)先選擇函數(shù)索引方案(簡化流程、節(jié)省存儲空間);
  • 若查詢頻率極高且對性能要求苛刻:可選擇生成列(STORED模式)+索引(物理存儲列,查詢更快)。

五、注意事項

  1. 索引字段類型匹配:JSON提取結(jié)果需轉(zhuǎn)換為與業(yè)務(wù)數(shù)據(jù)匹配的類型(如emailCHAR,數(shù)字ID用INT),避免類型轉(zhuǎn)換導(dǎo)致索引失效;
  2. 表達式一致性:函數(shù)索引查詢時,WHERE條件中的表達式需與索引定義完全一致(含CAST、排序規(guī)則),否則無法命中索引;
  3. JSON路徑正確性:JSON路徑(如$.request.email)需嚴(yán)格匹配JSON結(jié)構(gòu),若JSON嵌套層級變化,需同步更新索引表達式;
  4. 性能監(jiān)控:無論哪種方案,均需通過EXPLAINSHOW PROFILE等工具監(jiān)控索引使用情況,避免因SQL改寫導(dǎo)致索引失效。

六、總結(jié)

MySQL雖不支持直接索引JSON列,但通過“生成列”和“函數(shù)索引”兩種間接方案,可高效索引JSON中的特定字段,滿足業(yè)務(wù)查詢需求。實際應(yīng)用中,需根據(jù)MySQL版本、查詢頻率、存儲空間等因素選擇合適方案:低版本優(yōu)先用生成列,高版本優(yōu)先用函數(shù)索引。掌握這兩種方案,可充分發(fā)揮JSON的靈活性與索引的高效性,平衡數(shù)據(jù)存儲與查詢性能。

以上就是一文詳解MySQL JSON字段索引設(shè)置的具體方案的詳細(xì)內(nèi)容,更多關(guān)于MySQL JSON字段索引設(shè)置的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • mysql問題之slow log中出現(xiàn)大量的binlog dump記錄的解決方法

    mysql問題之slow log中出現(xiàn)大量的binlog dump記錄的解決方法

    今天在查看mysql中發(fā)現(xiàn)比較慢,然后我使用了slow log,發(fā)現(xiàn)出現(xiàn)了大量的binlog dump記錄,下面我來給大家整理一下這個問題的解決辦法
    2013-09-09
  • Mysql使用on update current_timestamp問題

    Mysql使用on update current_timestamp問題

    這篇文章主要介紹了Mysql使用on update current_timestamp問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 詳解如何利用Xtrabackup進行mysql增量備份

    詳解如何利用Xtrabackup進行mysql增量備份

    這篇文章主要為大家介紹了如何利用Xtrabackup進行mysql增量備份詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • mysql連接器之mysql-connector-java問題

    mysql連接器之mysql-connector-java問題

    這篇文章主要介紹了mysql連接器之mysql-connector-java問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • MySQL sysdate()函數(shù)的具體使用

    MySQL sysdate()函數(shù)的具體使用

    本文主要介紹了MySQL sysdate()函數(shù)的具體使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • mysql 8.0.22 安裝配置圖文教程

    mysql 8.0.22 安裝配置圖文教程

    這篇文章主要為大家詳細(xì)介紹了mysql 8.0.22 安裝配置圖文教程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • mysql如何按首字母進行檢索數(shù)據(jù)

    mysql如何按首字母進行檢索數(shù)據(jù)

    這篇文章介紹了如何根據(jù)學(xué)生的首字母檢索學(xué)生信息的需求,并提供了一種不增加表字段的實現(xiàn)方法,通過利用漢字的拼音排序特性,結(jié)合數(shù)據(jù)庫的排序和轉(zhuǎn)換函數(shù),實現(xiàn)了根據(jù)首字母模糊匹配檢索學(xué)生信息的功能
    2024-11-11
  • MySQL無法輸入中文字符問題的解決辦法

    MySQL無法輸入中文字符問題的解決辦法

    MySQL無法輸入中文的問題大多是由于字符集不匹配所導(dǎo)致的,下面這篇文章主要給大家介紹了關(guān)于MySQL無法輸入中文字符問題的解決辦法,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • Debian中完全卸載MySQL的方法

    Debian中完全卸載MySQL的方法

    這篇文章主要介紹了Debian中完全卸載MySQL的方法,同時介紹了清理方法,可以做到徹底卸載mysql,需要的朋友可以參考下
    2014-06-06
  • 淺談mysql的索引設(shè)計原則以及常見索引的區(qū)別

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

    下面小編就為大家?guī)硪黄獪\談mysql的索引設(shè)計原則以及常見索引的區(qū)別。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03

最新評論