搜尋
首頁資料庫mysql教程MySQL怎麼為JSON欄位建立索引

    多值索引簡介

    MySQL 8.0.17 開始, InnoDB支援建立多值索引(Multi-Valued Indexes) ,該索引是在JSON儲存值數組的資料列上定義的二級索引,對於單一資料記錄可以有多個索引記錄。此類索引特定的語法定義:

    CAST(expression AS type ARRAY),例如CAST(data->'$.zipcode' AS UNSIGNED ARRAY)。跟普通索引一樣,也可以在EXPLAIN中查看。

    建立多值索引

    跟其他索引一樣,多值索引可以在建表時添加,也可以透過ALTER TABLE或CREATE INDEX建立。

    JSON物件欄位索引

    語法

    ALTER TABLE customers ADD INDEX idx_mv_custinfo_list( ( CAST( custinfo -> '$.key' AS UNSIGNED array ) ) );

    注意:這裡在CAST語法外面有兩層單括號! ,如果少寫一個會報錯!

    測試案例

    PS:文中的案例是參考官方文件中的案例,只是作為測試,所以在命名等方面並不怎麼規範,實際開發過程中要嚴格遵守公司團隊的開發規範,不要偷懶!

    DROP TABLE IF EXISTS `customers`;
    /*建表语句*/
    CREATE TABLE customers ( 
    	id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    	modified DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    	custinfo JSON NOT NULL 
    );
    /*插入写测试数据*/
    INSERT INTO customers
    VALUES
    	( NULL, NOW(), '{"key":94582,"value":"asdf"}' ),
    	( NULL, NOW(), '{"key":94568,"value":"gjgasdasdf"}' ),
    	( NULL, NOW(), '{"key":94477,"value":"ghasdfsdf"}' ),
    	( NULL, NOW(), '{"key":94536,"value":"hagsdfgdf"}' ),
    	( NULL, NOW(), '{"key":94507,"value":"wasfgjdf"}' );
    /*添加多值索引*/
    ALTER TABLE customers ADD INDEX idx_mv_custinfo_list( ( CAST( custinfo -> '$.key' AS UNSIGNED array)) );
    /*测试 MEMBER OF 语法*/
    SELECT
    	* 
    FROM
    	customers 
    WHERE
    	94507 MEMBER OF ( custinfo -> '$.key' );
    /*测试 JSON_CONTAINS 语法*/
    SELECT
    	* 
    FROM
    	customers 
    WHERE
    	JSON_CONTAINS(
    		custinfo -> '$.key',
    	CAST( '[94582]' AS JSON ));
    /*测试 JSON_OVERLAPS 语法*/
    SELECT
    	* 
    FROM
    	customers 
    WHERE
    	JSON_OVERLAPS (
    		custinfo -> '$.key',
    	CAST( '[94477]' AS JSON ));

    檢視執行計畫發現可以使用到索引:

    MySQL怎麼為JSON欄位建立索引

    如果需要給字元類型建立多值索引,則必須是utf8mb4字元集且排序規則是utf8mb4_0900_as_cs,否則報錯該版本不支援: 

    如果要為binary二進位字串建立多值索引的話,則排序規則必須是binary,否則報錯不支援。

    MySQL怎麼為JSON欄位建立索引

    修改排序規則後可成功新增索引:

    MySQL怎麼為JSON欄位建立索引

    JSON陣列物件索引

    語法

    ALTER TABLE customers ADD INDEX idx_mv_custinfo_list( ( CAST( custinfo -> '$[*].key' AS UNSIGNED array ) ) );

    注意:這裡在CAST語法外面有兩層單括號!如果少寫一個會報錯!

    測試案例

    DROP TABLE IF EXISTS `customers`;
    /*建表语句*/
    CREATE TABLE customers ( 
    	id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    	modified DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    	custinfo JSON NOT NULL 
    );
    /*插入写测试数据*/
    INSERT INTO customers
    VALUES
    	( NULL, NOW(), '[{"key":94582},{"key":94536}]'),
    	( NULL, NOW(), '[{"key":94568},{"key":94507},{"key":94582}]'),
    	( NULL, NOW(), '[{"key":94477},{"key":94507}]'),
    	( NULL, NOW(), '[{"key":94536}]'),
    	( NULL, NOW(), '[{"key":94507},{"key":94582}]');
    /*添加多值索引*/
    ALTER TABLE customers ADD INDEX idx_mv_custinfo_list( ( CAST( custinfo -> '$[*].key' AS UNSIGNED array)) );
    /*测试 MEMBER OF 语法*/
    SELECT
    	* 
    FROM
    	customers 
    WHERE
    	94507 MEMBER OF ( custinfo -> '$[*].key' );
    /*测试 JSON_CONTAINS 语法*/
    SELECT
    	* 
    FROM
    	customers 
    WHERE
    	JSON_CONTAINS(
    		custinfo -> '$[*].key',
    	CAST( '[94582, 94507]' AS JSON ));
    /*测试 JSON_OVERLAPS 语法*/
    SELECT
    	* 
    FROM
    	customers 
    WHERE
    	JSON_OVERLAPS (
    		custinfo -> '$[*].key',
    	CAST( '[94477, 94582]' AS JSON ));

    查看執行計劃發現可以使用到索引:

    MySQL怎麼為JSON欄位建立索引

    ##在組合索引中創建多值索引

    語法

    語法跟普通組合索引差不多,同樣也遵守最左匹配原則:

    ALTER TABLE customers ADD INDEX idx_age_custinfo$list_modified
    ( age, (CAST( custinfo -> '$[*].key' AS UNSIGNED ARRAY )), modified );

    注意:這裡在CAST語法外面需要使用小括號括起來!

    測試案例

    DROP TABLE IF EXISTS `customers`;
    /*建表语句*/
    CREATE TABLE customers ( 
    	id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    	age tinyint(4) not null,
    	modified DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    	custinfo JSON NOT NULL 
    );
    /*插入写测试数据*/
    INSERT INTO customers
    VALUES
    	( NULL, 21, NOW(), '[{"key":94582},{"key":94536}]'),
    	( NULL, 22, NOW(), '[{"key":94568},{"key":94507},{"key":94582}]'),
    	( NULL, 23, NOW(), '[{"key":94477},{"key":94507}]'),
    	( NULL, 24, NOW(), '[{"key":94536}]'),
    	( NULL, 25, NOW(), '[{"key":94507},{"key":94582}]');
    /*添加多值索引*/
    alter table customers DROP INDEX idx_age_custinfo$list_modified ;
    ALTER TABLE customers ADD INDEX idx_age_custinfo$list_modified ( age, (CAST( custinfo -> '$[*].key' AS UNSIGNED ARRAY )),modified );
    ALTER TABLE customers ADD INDEX idx_age_custinfo$list_modified ((CAST( custinfo -> '$[*].key' AS UNSIGNED ARRAY )), age,modified  );
    ALTER TABLE customers ADD INDEX idx_age_custinfo$list_modified ( age,modified, (CAST( custinfo -> '$[*].key' AS UNSIGNED ARRAY )) );
    /*测试 MEMBER OF 语法*/
    SELECT
    	* 
    FROM
    	customers 
    WHERE
    	94536 MEMBER OF ( custinfo -> '$[*].key' ) and modified = '2021-08-05 10:36:34' and age = 21;

    查看執行計劃發現可以使用到索引:

    MySQL怎麼為JSON欄位建立索引

    多值索引的限制

    • 一個多值索引只允許包含一個屬性的值

    • 該索引目前只支援三個語法

    目前只有MEMBER OF、 JSON_CONTAINS()、 JSON_OVERLAB()三種語法可以使用到多值索引。

    • 索引值必須轉換成陣列

    #( CAST( custinfo -> '$.key' AS UNSIGNED array)),語法中的array是可以不加的,之所以要強制加是因為如果不加就不是數組結構,不是數組結構就沒法直接使用上述三個語法,需要通過JSON_ARRAY()等方法轉換後才能使用,這樣就會導致索引失效!因此不管需要加索引的字段是單一值的字段還是數組字段,都要加上array關鍵字。

    • 該索引不支援用於表格關聯

    • #不能結合前綴索引

    • #不支援在線創建多值索引

    #這句話的意思是該操作使用ALGORITHM=COPY,即透過新建一張表結構,再將資料複製過去的方式實現索引的建立。因此該過程中不允許DML操作。

    • 多值索引對字元集類型欄位有明確的要求

    binary字元集的排序規則必須是binary

    utf8mb4字元集的排序規則必須是utf8mb4_0900_as_cs

    其他任何字元集或排序規則都不能建立多值索引,建立時會錯誤目前版本不支援。

    應用場景

    多值索引的應用程式場景非常廣泛!有了他之後很多關聯關係表都可以不用了!舉個簡單的例子:用戶標籤,很多場景下會給用戶貼上各種標籤,比如1高2富3帥,為了後續的更高效的做統計或篩選查詢,我們不能直接將這個標籤作為一個字段存儲,因為沒有索引查詢效率不高,所以很多時候會使用一張關聯關係表來存儲用戶-標籤的關係。但是現在有了多值索引,我們就可以將標籤作為一個欄位儲存了!

    這只是其中一個小場景,類似的場景非常多,使用者可以換成任何事物,標籤也可以換成其他任何屬性,只要是這個事物存在多種屬性值就行,存在一個多對多關係,那麼在沒有需要這個屬性與其他表格做表格關聯的請況下),都可以使用多值索引實作!多值索引不支援表關聯,因此如果需要用該欄位在做表關聯的話就不合適了。

    以上是MySQL怎麼為JSON欄位建立索引的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    陳述
    本文轉載於:亿速云。如有侵權,請聯絡admin@php.cn刪除
    在MySQL中使用視圖的局限性是什麼?在MySQL中使用視圖的局限性是什麼?May 14, 2025 am 12:10 AM

    mysqlviewshavelimitations:1)他們不使用Supportallsqloperations,限制DatamanipulationThroughViewSwithJoinsOrsubqueries.2)他們canimpactperformance,尤其是withcomplexcomplexclexeriesorlargedatasets.3)

    確保您的MySQL數據庫:添加用戶並授予特權確保您的MySQL數據庫:添加用戶並授予特權May 14, 2025 am 12:09 AM

    porthusermanagementinmysqliscialforenhancingsEcurityAndsingsmenting效率databaseoperation.1)usecReateusertoAddusers,指定connectionsourcewith@'localhost'or@'%'。

    哪些因素會影響我可以在MySQL中使用的觸發器數量?哪些因素會影響我可以在MySQL中使用的觸發器數量?May 14, 2025 am 12:08 AM

    mysqldoes notimposeahardlimitontriggers,butacticalfactorsdeterminetheireffactective:1)serverConfiguration impactactStriggerGermanagement; 2)複雜的TriggerSincreaseSySystemsystem load; 3)largertablesslowtriggerperfermance; 4)highConconcConcrencerCancancancancanceTigrignecentign; 5); 5)

    mysql:存儲斑點安全嗎?mysql:存儲斑點安全嗎?May 14, 2025 am 12:07 AM

    Yes,it'ssafetostoreBLOBdatainMySQL,butconsiderthesefactors:1)StorageSpace:BLOBscanconsumesignificantspace,potentiallyincreasingcostsandslowingperformance.2)Performance:LargerrowsizesduetoBLOBsmayslowdownqueries.3)BackupandRecovery:Theseprocessescanbe

    mySQL:通過PHP Web界面添加用戶mySQL:通過PHP Web界面添加用戶May 14, 2025 am 12:04 AM

    通過PHP網頁界面添加MySQL用戶可以使用MySQLi擴展。步驟如下:1.連接MySQL數據庫,使用MySQLi擴展。 2.創建用戶,使用CREATEUSER語句,並使用PASSWORD()函數加密密碼。 3.防止SQL注入,使用mysqli_real_escape_string()函數處理用戶輸入。 4.為新用戶分配權限,使用GRANT語句。

    mysql:blob和其他無-SQL存儲,有什麼區別?mysql:blob和其他無-SQL存儲,有什麼區別?May 13, 2025 am 12:14 AM

    mysql'sblobissuitableForStoringBinaryDataWithInareLationalDatabase,而ilenosqloptionslikemongodb,redis和calablesolutionsolutionsolutionsoluntionsoluntionsolundortionsolunsonstructureddata.blobobobissimplobisslowdeperformberbutslowderformandperformancewithlararengedata;

    mySQL添加用戶:語法,選項和安全性最佳實踐mySQL添加用戶:語法,選項和安全性最佳實踐May 13, 2025 am 12:12 AM

    toaddauserinmysql,使用:createUser'username'@'host'Indessify'password'; there'showtodoitsecurely:1)choosethehostcarecarefullytocon trolaccess.2)setResourcelimitswithoptionslikemax_queries_per_hour.3)usestrong,iniquepasswords.4)Enforcessl/tlsconnectionswith

    MySQL:如何避免字符串數據類型常見錯誤?MySQL:如何避免字符串數據類型常見錯誤?May 13, 2025 am 12:09 AM

    toAvoidCommonMistakeswithStringDatatatPesInMysQl,CloseStringTypenuances,chosethirtightType,andManageEngencodingAndCollat​​ionsEttingSefectery.1)usecharforfixed lengengtrings,varchar forvariable-varchar forbariaible length,andtext/blobforlargerdataa.2 seterters seterters seterters

    See all articles

    熱AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智慧驅動的應用程序,用於創建逼真的裸體照片

    AI Clothes Remover

    AI Clothes Remover

    用於從照片中去除衣服的線上人工智慧工具。

    Undress AI Tool

    Undress AI Tool

    免費脫衣圖片

    Clothoff.io

    Clothoff.io

    AI脫衣器

    Video Face Swap

    Video Face Swap

    使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

    熱門文章

    熱工具

    EditPlus 中文破解版

    EditPlus 中文破解版

    體積小,語法高亮,不支援程式碼提示功能

    SublimeText3 英文版

    SublimeText3 英文版

    推薦:為Win版本,支援程式碼提示!

    MantisBT

    MantisBT

    Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

    SublimeText3 Linux新版

    SublimeText3 Linux新版

    SublimeText3 Linux最新版

    SecLists

    SecLists

    SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。