MySQL存储过程因为字符集不同导致执行慢

业务反馈线上一个存储过程执行很慢,导致业务超时较多,而存储过程比较简单,就是一个简单的判断逻辑然后delete一条记录,而且delete语句是有索引的。

表结构如下:

CREATE TABLE `table1` (

  `BaseName` varchar(255) NOT NULL COMMENT '相对路径名(相对于上层目录)',

  `Bucket` mediumtext NOT NULL COMMENT '目录所属Bucket(业务名)',

  `DirUuid` varchar(64) NOT NULL COMMENT '父目录Uuid',

  `IsDir` tinyint(1) NOT NULL COMMENT '是否是文件夹',


   xxx

  PRIMARY KEY (`DirUuid`,`BaseName`),

  KEY `origin` (`DirUuid`,`OriginBaseName`),

  KEY `dir` (`DirUuid`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

存储过程如下:

 CREATE DEFINER=`xxx`@`%` PROCEDURE `PDelete`(                                                          

  IN `base_name` varchar(255),                                                     

  IN `dir_uuid` varchar(36),                                                       

  IN `IsDir` tinyint(1))

BEGIN                                                                              

    DECLARE t_error INTEGER DEFAULT 0;                                             

    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET t_error=1;                    


    START TRANSACTION;                                                             

        IF IsDir = 1 THEN                                                       

            delete from table1 where `DirUuid` = dir_uuid and `BaseName` = base_name;

            delete from table2 where `DirUuid` = dir_uuid and `Dir` = base_name;

        ELSE                                                                    

            delete from table2 where (`DirUuid` = dir_uuid and `BaseName` = base_name) or (`DirUuid` = dir_uuid and `OriginBaseName` = base_name);

        END IF;                                                                    

    IF t_error = 1 THEN                                                            

        ROLLBACK;                                                                  

    ELSE                                                                           

        COMMIT;                                                                    

    END IF;                                                                        


    select t_error;                                                                

END

然后单独调用存储过程:

mysql> call PDelete('5', 'd3b18237-07ee-43bd-be15-aa7b7399f94b', 0);

+---------+

| t_error |

+---------+

|       0 |

+---------+

1 row in set (3.47 sec)

竟然需要3.47s,从存储过程的定义以及表结构来看,怎么也不用3.47s.

当单独拿出delete语句来执行看看:

mysql> delete from table1 where (`DirUuid` = 'd3b18237-07ee-43bd-be15-aa7b7399f94b' and `BaseName` = '5') or (`DirUuid` = 'd3b18237-07ee-43bd-be15-aa7b7399f94b' and `OriginBaseName` = '5');

Query OK, 0 rows affected (0.00 sec)

执行很快 ,和存储过程调用差别了很大。而且存储过程中也没有其他特别的逻辑,没有循序,没有等待,不应该这么慢才对,只有可能耗时的地方就是delete语句,

存储过程中delete和外部单独执行的delete语句,看上去完全一致,但是我们还需要判断,where条件的类型是否一致,会不会是类型不一致导致的执行慢?

然后对比存储存储过程和表结构,where条件给定的类型也是一致的。那还会有什么原因导致执行很慢呢,还有一种情况没考虑到:字符集,如何表的字符集和where条件中值字符集不一致,

也是有可能导致索引失效的,进行导致执行变慢。这里就需要理解一下调用存储过程是如何使用字符集的,在官方介绍中有如下说明:

For character data types, if there is a CHARACTER SET attribute in the declaration, the specified

character set and its default collation is used. If the COLLATE attribute is also present, that collation is

used rather than the default collation.

If CHARACTER SET and COLLATE attributes are not present, the database character set and collation in

effect at routine creation time are used. To avoid having the server use the database character set and

collation, provide explicit CHARACTER SET and COLLATE attributes for character data parameters.

If you change the database default character set or collation, stored routines that use the database

defaults must be dropped and recreated so that they use the new defaults.

The database character set and collation are given by the value of the character_set_database

and collation_database system variables. For more information, see Section 10.1.3.2, “Database

Character Set and Collation”.

如果存储过程中定义参数时,没有指定字符集,会默认读取创建存储过程时的全局变量character_set_server,如果后续变更了字符集,存储过程不会自动变更字符集,

需要删除重新创建存储过程,才能使得新的字符集生效。

由于创建存储过程时,没有指定字符集,因此采用的character_set_server指定的字符集 utf8mb4,那就意味着存储过程传参都是采用utf8mb4,那么存储过程中delete语句中value的字符集

就是utf8mb4,那再看看表的字符集,) ENGINE=InnoDB DEFAULT CHARSET=utf8; 是utf8的,是不兼容utfbmb4的,字符集不同从而导致索引失效,进而导致delete很慢,影响整个存储过程的执行效率。

解决办法很简单,两种方案均可:

1.调整character_set_server 为 utf8,然后重建存储过程即可,不重建的话,不会起作用。存储过程的字符集是以存储过程创建时character_set_server 为准。

2.将表的字符集更改为utf8mb4也可以。

两种方案选择代价较小的进行即可,我们这里由于是线上环境,更改字符集需要重启服务,因此选择转化表的字符集。

反过来,如果存储过程的字符集是utf8,而表的字符集是utf8mb4,那么是不会出现这个问题的,utf8mb4是兼容utf8的,这里需要注意一下。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容