电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

MySQL提取Json內部字段轉儲為數字

瀏覽:19日期:2023-10-01 09:54:15
目錄背景問題分析1、屬性值是 Json 格式的,需要使用 Json 操作函數處理2、字段內容不規范,亂七八糟3.又要抽取內容、又要格式化,記錄還有 900w+,太慢了最后執行結果比較數據導入比較總結

這只是一次簡單數據遷移的統計,數據量不大,麻煩的是一些中間步驟處理和思量。

沒有 SQL 優化、索引優化的內容,大家輕噴。

背景

用戶眼科屬性表記錄數大概 986w,目的是把大概 29w 記錄的屬性值(json 格式)的其中八個字段解析為數字,轉儲為統計表的記錄,用于圖表分析。

以下結構、數據都大部分我瞎謅的,不可當真

用戶眼科屬性表結構如下

CREATE TABLE `property` ( `id` int(11) NOT NULL AUTO_INCREMENT, `ownerId` int(11) NOT NULL COMMENT ’記錄ID或者模板ID’, `ownerType` tinyint(4) NOT NULL COMMENT ’類型。0:記錄 1:模板’, `recorderId` bigint(20) NOT NULL DEFAULT ’0’ COMMENT ’記錄者ID’, `userId` bigint(20) NOT NULL DEFAULT ’0’ COMMENT ’用戶ID’, `roleId` bigint(20) NOT NULL DEFAULT ’0’ COMMENT ’角色ID’, `type` tinyint(4) NOT NULL COMMENT ’字段類型。0:文本 1:備選項 2:時間 3:圖片 4:ICD10 9:新圖片’, `name` varchar(128) NOT NULL DEFAULT ’’ COMMENT ’字段名稱’, `value` mediumtext NOT NULL COMMENT ’字段值’, PRIMARY KEY (`id`), UNIQUE KEY `idxOwnerIdOwnerTypeNameType` (`ownerType`,`ownerId`,`name`,`type`) USING BTREE, KEY `idxUserIdRoleIdRecorderIdName` (`userId`,`roleId`,`recorderId`,`name`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=’屬性’;問題分析1、屬性值是 Json 格式的,需要使用 Json 操作函數處理

因為屬性值是 Json 格式的,如下。較大的一個 Json,但是只需要其中 8 個字段值,提取出來分門別類歸為不同統計指標下。

{ ...... 'sight': {'nakedEye': { 'left': '0.9', 'right': '0.6'},'correction': { 'left': '1', 'right': '1'} }, ...... 'axialLength': {'left': '21','right': '12' }, 'korneaRadius': {'left': '34','right': '33' }, ......}

所以,需要用到 Json 操作函數:json_extract(value,’$.key1.key2’)。

但是需要注意的是這個函數提取的值是帶''。比如對上述記錄執行json_extract(value,’$.sight.nakedEye.left’)的結果是'22';也可能字段值是空字符串,那結果就是''。

所以,需要使用 replace函數把結果中的 '' 刪除掉,最后提取字段的表達式就是:replace(json_extract(value,’$.sight.nakedEye.left’),’'’,’’)。

如果字段不存在的話,結果就是 NULL;無論是外層 sight 不存在,或是內層 left 不存在。

2、字段內容不規范,亂七八糟

理想下,填寫的都是規范數字,那經過上面那一步就可以提取完直接導入新表。

但是,現實很殘酷,填的東西那叫一個亂七八糟。比如:

數字 + 備注:1(配合欠佳)、1-+(我猜這是想表示偏高或偏低) 數字 + 單位:跟上面相似,1mm 多數值或區間:22.52/42.45、1-5 純文本描述:不配合、無法記錄 文本、數字混雜描述:較上次增長 10、<1、小于1、BD234/KD23

沒辦法,找產品和業務對情況,好在不多,就 4000 多條,大致掃一下心里有數。得出以下幾條解決方案:

數字開頭:數字開頭都是正確記錄的數據,省略掉文字描述即可 多數值或區間:取最前面的數即可 純文本:說明沒有數據,排除掉 文本、數字混雜:具體問題具體分析,把其他處理掉之后看還有多少

具體怎么做呢?

第一步:排除正常的數字數據和空數據

WHERE `nakedEyeLeft` REGEXP ’[^0-9.]’ = 1 // 這個已經可以排除 null 了 AND `nakedEyeLeft` != ’’

第二步:如果不包含數字,將其設置 NULL 或空字符串

SET nakedEyeLeft = IF(nakedEyeLeft NOT regexp ’[0-9]’, ’’, nakedEyeLeft)

第三步:提取數字開頭的數據的首個數值

SET nakedEyeLeft = IF((nakedEyeLeft + 0 = 0), nakedEyeLeft, nakedEyeLeft + 0)

結合起來就是

SET nakedEyeLeft = IF(nakedEyeLeft NOT regexp ’[0-9]’’’, ’’, IF((nakedEyeLeft + 0 = 0), nakedEyeLeft, nakedEyeLeft + 0))WHERE `nakedEyeLeft` REGEXP ’[^0-9.]’ = 1 // 這個已經可以排除 null 了 AND `nakedEyeLeft` != ’’

PS:處理一個字段的SQL 看著就簡單,但是因為批量一次處理 8 個字段,組合起來就很長。

千萬注意不要寫錯字段。

最后剩下的就是第四類:文本、數字混雜,40 多條。

有些看著簡單的,可以用正則自動化處理,比如<1、小于1。

記錄的增長值,需要查找上次記錄進行計算:較上次增長 10。

剩下有點復雜的,就需要人為處理,提取出可用數據,比如BD234/KD23

不知道看到這里的各位是不是也覺得有些麻煩呢?

我也以為咬著牙搞了,結果業務說直接處理成 0,到時候發現是 0 的話,可以通過頁面重新保存的。

就不需要判斷是不是數字打頭了,直接 + 0;如果是數字打頭,會保留開頭的數字;否則 = 0。

那最后數據格式化SQL:

UPDATE property SET nakedEyeLeft = IF(nakedEyeLeft NOT regexp ’[0-9]’’’, ’’, nakedEyeLeft + 0)WHERE `nakedEyeLeft` REGEXP ’[^0-9.]’ = 1 // 這個已經可以排除 null 了 AND `nakedEyeLeft` != ’’;3.又要抽取內容、又要格式化,記錄還有 900w+,太慢了

property 表有 900w+ 的數據,而所需記錄的條件,只有name、ownerType、type是可知的,沒法命中現有的索引。

如果直接查找的話,直接就是全表掃描,外加數據提取和格式化;更何況還需要關聯其他表,補充統計指標的一些其他字段。

這種情況下,直接導入統計表的話,結果就是把兩張表+關聯表一起鎖較長時間,期間沒法更改和插入,這樣不大現實。

減少掃描行數

做法一:給 name、ownerType、type 加上索引,將掃描記錄縮減到 20 w。

但是問題是900w 數據加索引,用完需要刪除索引(因為不是業務情況需要),就會導致兩次波動;

再加上后續處理鎖表時長,問題還是很大。

做法二:將一個記錄較少的表做驅動表,這個表可以關聯目標表。

CREATE TABLE `property` ( `ownerId` int(11) NOT NULL COMMENT ’記錄ID或者模板ID’, `ownerType` tinyint(4) NOT NULL COMMENT ’類型。0:記錄 1:模板’, `type` tinyint(4) NOT NULL COMMENT ’字段類型。0:文本 1:備選項 2:時間 3:圖片 4:ICD10 9:新圖片’, `name` varchar(128) NOT NULL DEFAULT ’’ COMMENT ’字段名稱’, `value` mediumtext NOT NULL COMMENT ’字段值’, 省略其他字段 UNIQUE KEY `idxOwnerIdOwnerTypeNameType` (`ownerType`,`ownerId`,`name`,`type`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=’屬性’;

表中ownerId 可以關聯到記錄表,加上之前的條件name、ownerType、type,如此剛好命中 并``idxOwnerIdOwnerTypeNameType (ownerType,ownerId,name,type) 。

CREATE TABLE `medicalrecord` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL DEFAULT ’’ COMMENT ’記錄名稱’, `type` tinyint(4) NOT NULL DEFAULT ’0’ COMMENT ’記錄類型。’, 省略其他字段 KEY `idxName` (`name`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=’記錄’;

記錄表可以通過 name=’眼科記錄’命中索引idxName,掃描行數只有2w,加上屬性表 29w,最后掃描行數只有 30w 左右,比之全表掃描屬性表少了 30 倍!!!。

避免數據提取和格式化的鎖表時長

因為存在 8 個字段,每個字段都需要提取和格式化,中間還需要進行判斷。這樣子一個 SQL 里面同樣的提取和格式化操作就要多次執行了。

所以,為了避免這樣的問題,需要中間表暫存提取和格式化結果。

CREATE TABLE `propertytmp` ( `id` int(11) NOT NULL AUTO_INCREMENT, `value` mediumtext NOT NULL COMMENT ’字段值’, `nakedEyeLeft` varchar(255) DEFAULT NULL COMMENT ’視力-裸眼-左眼’, `nakedEyeRight` varchar(255) DEFAULT NULL COMMENT ’視力-裸眼-右眼’, `correctionLeft` varchar(255) DEFAULT NULL COMMENT ’視力-矯正-左眼’, `correctionRight` varchar(255) DEFAULT NULL COMMENT ’視力-矯正-右眼’, `axialLengthLeft` varchar(255) DEFAULT NULL COMMENT ’眼軸長度-左眼’, `axialLengthRight` varchar(255) DEFAULT NULL COMMENT ’眼軸長度-右眼’, `korneaRadiusLeft` varchar(255) DEFAULT NULL COMMENT ’角膜曲率-左眼’, `korneaRadiusRight` varchar(255) DEFAULT NULL COMMENT ’角膜曲率-右眼’, `updated` datetime NOT NULL COMMENT ’更新時間’, `deleted` tinyint(1) NOT NULL DEFAULT ’0’, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

先將數據導入該表,在此基礎上做提取,然后格式化。

最后執行結果比較數據導入比較

結果:全表掃描屬性表導入中間表(40s),屬性表新增索引+導入(6s + 3s),關聯導入(1.4s)。

因為需要關聯其他表,并沒有預測的那么理想。

中間表數據提取:7.5s

UPDATE `propertytmp` SET nakedEyeLeft = REPLACE(json_extract(value,’$.sight.axialLength.left’),’'’,’’),nakedEyeLeft = REPLACE(json_extract(value,’$.sight.nakedEye.left’),’'’,’’),nakedEyeRight = REPLACE(json_extract(value,’$.sight.nakedEye.right’),’'’,’’),correctionLeft = REPLACE(json_extract(value,’$.sight.correction.left’),’'’,’’),correctionRight = REPLACE(json_extract(value,’$.sight.correction.right’),’'’,’’),axialLengthLeft = REPLACE(json_extract(value,’$.axialLength.left’),’'’,’’),axialLengthRight = REPLACE(json_extract(value,’$.axialLength.right’),’'’,’’),korneaRadiusLeft = REPLACE(json_extract(value,’$.korneaRadius.left’),’'’,’’),korneaRadiusRight = REPLACE(json_extract(value,’$.korneaRadius.right’),’'’,’’);

中間表數據格式化:2.3s

正則判斷比我想象的要快啊

UPDATE propertytmp SET nakedEyeLeft = IF(nakedEyeLeft NOT REGEXP ’[0-9]’ AND nakedEyeLeft != ’’, ’’, nakedEyeLeft + 0), nakedEyeRight = IF(nakedEyeRight NOT REGEXP ’[0-9]’ AND nakedEyeRight != ’’, ’’, nakedEyeRight + 0), correctionLeft = IF(correctionLeft NOT REGEXP ’[0-9]’ AND correctionLeft != ’’, ’’, correctionLeft + 0),correctionRight = IF(correctionRight NOT REGEXP ’[0-9]’ AND correctionRight != ’’, ’’, correctionRight + 0),axialLengthLeft = IF(axialLengthLeft NOT REGEXP ’[0-9]’ AND axialLengthLeft != ’’, ’’, axialLengthLeft + 0),axialLengthRight = IF(axialLengthRight NOT REGEXP ’[0-9]’ AND axialLengthRight != ’’, ’’, axialLengthRight + 0),korneaRadiusLeft = IF(korneaRadiusLeft NOT REGEXP ’[0-9]’ AND korneaRadiusLeft != ’’, ’’, korneaRadiusLeft + 0),korneaRadiusRight = IF(korneaRadiusRight NOT REGEXP ’[0-9]’ AND korneaRadiusRight != ’’, ’’, korneaRadiusRight + 0)WHERE (`nakedEyeLeft` REGEXP ’[^0-9.]’ = 1 AND `nakedEyeLeft` != ’’) OR (`nakedEyeRight` REGEXP ’[^0-9.]’ = 1 AND `nakedEyeRight` != ’’) OR (`correctionLeft` REGEXP ’[^0-9.]’ = 1 AND `correctionLeft` != ’’) OR (`correctionRight` REGEXP ’[^0-9.]’ = 1 AND `correctionRight` != ’’) OR (`axialLengthLeft` REGEXP ’[^0-9.]’ = 1 AND `axialLengthLeft` != ’’) OR (`axialLengthRight` REGEXP ’[^0-9.]’ = 1 AND `axialLengthRight` != ’’) OR (`korneaRadiusLeft` REGEXP ’[^0-9.]’ = 1 AND `korneaRadiusLeft` != ’’) OR (`korneaRadiusRight` REGEXP ’[^0-9.]’ = 1 AND `korneaRadiusRight` != ’’);

統計指標中間表

因為實際導入統計指標表時,還需要排除為空數據,以及關聯其他表做補充。

為了減少對指標表的影響,又建了指標表的中間表,結構完全一致,ID自增是目標表 + 10000。

將屬性中間表的數據導入指標中間表,最后直接 INSERT ... SELECT FROM,就很快了。

當然這步其實有點矯枉過正了,但是為了避免線上的一些波動,還是謹慎一些較好。

總結

這是一次簡單的數據遷移經歷記錄。

沒有索引優化、SQL優化的內容,只是覺得大家需要有這種關注性能和對用戶影響的考慮。

到此這篇關于MySQL提取Json內部字段轉儲為數字的文章就介紹到這了,更多相關MySQL提取Json轉儲為數字內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: MySQL 數據庫
相關文章:
主站蜘蛛池模板: Win10系统下载_32位/64位系统/专业版/纯净版下载 | 广州印刷厂_广州彩印厂-广州艺彩印务有限公司 | 温州在线网| 塑钢件_塑钢门窗配件_塑钢配件厂家-文安县启泰金属制品有限公司 深圳南财多媒体有限公司介绍 | 洁净实验室工程-成都手术室净化-无尘车间装修-四川华锐净化公司-洁净室专业厂家 | 中开泵,中开泵厂家,双吸中开泵-山东博二泵业有限公司 | 新中天检测有限公司青岛分公司-山东|菏泽|济南|潍坊|泰安防雷检测验收 | 儋州在线-儋州招聘找工作、找房子、找对象,儋州综合生活信息门户! | 北京四合院出租,北京四合院出售,北京平房买卖 - 顺益兴四合院 | 档案密集柜_手动密集柜_智能密集柜_内蒙古档案密集柜-盛隆柜业内蒙古密集柜直销中心 | 比亚迪叉车-比亚迪电动叉车堆垛车托盘车仓储叉车价格多少钱报价 磁力去毛刺机_去毛刺磁力抛光机_磁力光饰机_磁力滚抛机_精密金属零件去毛刺机厂家-冠古科技 | 真石漆,山东真石漆,真石漆厂家,真石漆价格-山东新佳涂料有限公司 | MTK核心板|MTK开发板|MTK模块|4G核心板|4G模块|5G核心板|5G模块|安卓核心板|安卓模块|高通核心板-深圳市新移科技有限公司 | 便民信息网_家电维修,家电清洗,开锁换锁,本地家政公司 | 无纺布包装机|径向缠绕包装机|缠绕膜打包机-上海晏陵智能设备有限公司 | 杭州代理记账费用-公司注销需要多久-公司变更监事_杭州福道财务管理咨询有限公司 | 杭州厂房降温,车间降温设备,车间通风降温,厂房降温方案,杭州嘉友实业爽风品牌 | 学习安徽网| 酶联免疫分析仪-多管旋涡混合仪|混合器-莱普特科学仪器(北京)有限公司 | 江苏大隆凯科技有限公司| 南京展台搭建-南京展会设计-南京展览设计公司-南京展厅展示设计-南京汇雅展览工程有限公司 | 衡阳耐适防护科技有限公司——威仕盾焊接防护用品官网/焊工手套/焊接防护服/皮革防护手套 | 上海地磅秤|电子地上衡|防爆地磅_上海地磅秤厂家–越衡称重 | 亚克隆,RNAi干扰检测,miRNA定量检测-上海基屹生物科技有限公司 | 加盟店-品牌招商加盟-创业项目商机平台| 专业生产动态配料系统_饲料配料系统_化肥配料系统等配料系统-郑州鑫晟重工机械有限公司 | 餐饮小吃技术培训-火锅串串香培训「何小胖培训」_成都点石成金[官网] | 深圳侦探联系方式_深圳小三调查取证公司_深圳小三分离机构 | 闸阀_截止阀_止回阀「生产厂家」-上海卡比阀门有限公司 | 定量包装机,颗粒定量包装机,粉剂定量包装机,背封颗粒包装机,定量灌装机-上海铸衡电子科技有限公司 | 深圳善跑体育产业集团有限公司_塑胶跑道_人造草坪_运动木地板 | 合肥地磅_合肥数控切割机_安徽地磅厂家_合肥世佳电工设备有限公司 | arch电源_SINPRO_开关电源_模块电源_医疗电源-东佑源 | 【北京写字楼出租_写字楼租赁_办公室出租网/出售】-远行地产官网 | 精密冲床,高速冲床等冲压设备生产商-常州晋志德压力机厂 | 新疆系统集成_新疆系统集成公司_系统集成项目-新疆利成科技 | 无轨电动平车_轨道平车_蓄电池电动平车★尽在新乡百特智能转运设备有限公司 | 特材真空腔体_哈氏合金/镍基合金/纯镍腔体-无锡国德机械制造有限公司 | 企典软件一站式企业管理平台,可私有、本地化部署!在线CRM客户关系管理系统|移动办公OA管理系统|HR人事管理系统|人力 | 砂尘试验箱_淋雨试验房_冰水冲击试验箱_IPX9K淋雨试验箱_广州岳信试验设备有限公司 | 熔体泵|换网器|熔体齿轮泵|熔体计量泵厂家-郑州巴特熔体泵有限公司 |