实用户问咱们为甚么底下这个建表语句会履行失利,报错是Rowsizetoolarge....底下我就以这个例子登程讲一讲哄骗mysql怎样灵验地建表。本文哄骗的图片是从网络探求到的,不是我自身制做的,在此报酬图片的做家和占有者。CREATETABLEbad_table(col1varchar(20)NOTNULLDEFAULT,col2varchar()DEFAULTNULL,col3varchar()DEFAULTNULL,col4varchar()DEFAULTNULL,col5varchar()DEFAULTNULL,col6varchar(6)DEFAULTNULL,col7varchar(12)DEFAULTNULL,col8varchar(10)DEFAULTNULL,col9varchar(9)DEFAULTNULL,col10varchar(3)DEFAULTNULL,col11varchar(10)DEFAULTNULL,col12varchar(2)DEFAULTNULL,col13varchar(5)DEFAULTNULL,col14varchar(1)DEFAULTNULL,col15varchar(3)DEFAULTNULL,col16decimal(24,6)DEFAULTNULL,col17varchar(3)DEFAULTNULL,col18decimal(24,6)DEFAULTNULL,col19varchar(50)DEFAULTNULL,col20varchar(12)DEFAULTNULL,col21varchar(12)DEFAULTNULL,col22varchar(1)DEFAULTNULL,col23varchar(3)DEFAULTNULL,col24varchar(3)DEFAULTNULL,col25varchar()DEFAULTNULL,col26int(11)DEFAULTNULL,col27varchar(10)DEFAULTNULL,col28varchar(1)DEFAULTNULL,col29varchar(32)DEFAULTNULL,col30varchar()DEFAULTNULL,col31varchar()DEFAULTNULL,col32varchar()DEFAULTNULL,col33decimal(24,6)DEFAULTNULL,col34varchar(1)DEFAULTNULL,col35varchar()DEFAULTNULL,col36varchar(32)DEFAULTNULL,col37varchar(20)DEFAULTNULL,col38varchar(32)DEFAULTNULL,col39varchar(32)DEFAULTNULL,col40varchar(32)DEFAULTNULL,col41varchar(20)DEFAULTNULL,col42varchar(3)DEFAULTNULL,col43varchar(50)DEFAULTNULL,col44varchar(3)DEFAULTNULL,col45varchar(50)DEFAULTNULL,col46varchar()DEFAULTNULL,col47varchar(8)DEFAULTNULL,col48varchar(8)DEFAULTNULL,col49varchar(16)DEFAULTNULL,col50varchar(2)DEFAULTNULL,col51varchar(2)DEFAULTNULL,col52varchar(2)DEFAULTNULL,col53varchar(2)DEFAULTNULL,col54varchar(2)DEFAULTNULL,col55varchar(2)DEFAULTNULL,col56varchar(3)DEFAULTNULL,col57varchar(2)DEFAULTNULL,col58varchar(2)DEFAULTNULL,col59varchar(3)DEFAULTNULL,col60varchar(4)DEFAULTNULL,col61varchar(4)DEFAULTNULL,col62varchar(2)DEFAULTNULL,col63varchar(20)DEFAULTNULL,col64varchar(32)DEFAULTNULL,col65varchar(32)DEFAULTNULL,col66varchar()DEFAULTNULL,col67varchar(50)DEFAULTNULL,col68varchar(2)DEFAULTNULL,col69varchar(2)DEFAULTNULL,col70varchar(2)DEFAULTNULL,col71varchar(2)DEFAULTNULL,col72varchar(20)DEFAULTNULL,col73varchar(1)DEFAULTNULL,col74varchar(20)DEFAULTNULL,col75varchar(20)DEFAULTNULL,col76varchar(2)DEFAULTNULL,col77varchar(10)DEFAULTNULL,col78varchar(32)DEFAULTNULL,col79varchar(4)DEFAULTNULL,col80varchar(1)DEFAULTNULL,col81varchar(1)DEFAULTNULL,col82varchar(32)DEFAULTNULL,PRIMARYKEY(col1))ENGINE=InnoDBDEFAULTCHARSET=utf8ROW_FORMAT=DYNAMIC;这是一个来自于确实的客户的确实的运用中的表,这边隐去了客户的一齐音信,表名和列名也都颠末变革,去掉了关键音信,并且去掉了一齐的注解音信。这个表是一个界说不良的表,它有良多题目,本文就解析一下它的题目以及怎样才干更好地建表。这个表直寓目上去题目囊括1.过量的列2.良多列是最大长度在8之内的varchar范例3.有一些最大长度在几百的varchar列首先,过量的列致使一行希奇长,然则常常并不是每个字段都邑频频革新,云云那些频频革新的字段的革新开消就会较量大,由于首先过大的行致使一个页上头保存的行很少,纵然更动一行的一个字节,也需求完备地读取它地址的这全部页面。那末读取一个页面能够掷中的行就会较量少,就大概需求读取更多的页面来革新多个行,并且也需求写盘更多的页面。同时,还象征着纪录binlog和事件日记的价格也会增大(大概颠末优化能够部份地低沉这部份价格)。并且任何一行的buffer掷中率也会严峻低沉,对查问和革新的功能都邑低沉。同时,关于innodb来讲这还象征着当表有良多行(假使是几万万行)的时刻,b+树的高度会较量高,致使探求功夫变长。这边做一个浅显的盘算。假使这个表有1亿行,innodb_page_size=4k,由于innodb请求一页最少保存2行数据,那末主表的b+树至多会有5万万个叶节点页面,假使均匀每个内部节点页面能够保存笔纪录(每笔纪录保存{索引key,属下节点指针}),那末也即是^h1=5*10^7,能够懂得树的高度h1=4(单个根节点的高度是0),同时主表全豹管大略万个页面。这边假使innodb的b+树有较好的自均衡机制,不会形成任何一个左右子树高度差大于1的子树。纵然表的盘算公道每个叶节点页面能够保存一百行的话,那末全豹惟独万个叶节点页面,云云^h2=10^6,能够懂得h2=3,同时主表全豹管大略万个页面。因而可知行的密度和掷中率大幅增大,并且h2的树的探求途径会致使屡屡探求都均匀多一次页面读取。再做一个基于极其假使的盘算:假使主键很长,及至于内节点页面只可保存10笔纪录,那末h1将会变为8,这个主表的b+树将会有大略0万个内节点页面,共约万个页面;h2会变为6,这个主表的b+树将会有大略万个内节点页面,共约万个页面。后者的查问和革新的效率会比前者超出良多。也即是说,任何一个索引的key都最佳别过长,不然谁人索引的探求途径会较量长,并且buffer的效率(掷中率)会低沉。关于secondaryindex真理也相仿,并且由于它们的索引行会保存主键,因而主键的size也会影响到secondaryindex的效率。着末,innodb关于索引key的保存有必然的优化,囊括归并统一个索引纪录上头反复的字段,以及相邻索引纪录中相仿字段不反复保存等,会必然水平鼎新上头盘算的成绩,然则并不会有实质的鼎新。innodb的b+树布局以下图,本文不在此开展赘述。2.依据原SQL语句的注解能够懂得,这些短的varchar字段中,有底下这些是能够用更适合的范例的。从保存的空间效率来讲,每个varchar短字段(长度小于)还需求额外1个字节的空间,同时在mysqld内部的查问处置阶段,数值范例的字段的盘算和处置也会比字符串范例更高效一些。不过这些根基是微不够道的,不同不大。更重要的是哄骗的便利性方面,哄骗适合的范例在后续的开拓劳动中会有各式便利,这些数值范例的存在必定是有道理的,该当在适合的场面哄骗它们。长度在4之内的这些字段,属于这么几种:a.用于保存bool值,也即是保存(二元状况,是/否)。这类该当哄骗bool范例b.用于保存范例值,也即是保存(范例,分类,品种,级别,品级)等。这类该当哄骗enum范例。有人耽心enum预先没法先见一齐大概的罗列值,但其切实altertable中能够online方法(不需求copytable)更正列界说的方法补充更多的罗列值的,并且在表保存中罗列值是做为数字来保存的,每个字段至多2个字节。希奇是在查问,较量,般配的时刻是数字较量而不是字符串,因此效率会提高良多。c.长度在12之内的字段不公道的字段主假如用于保存日期功夫。该当哄骗datetime,保证便利和切确的盘算和查问日期和功夫,以及切确地索引。希奇是在帮助时区的处境下,纵然不哄骗datetime范例实在很难切确地盘算。3.关于那些最大长度在几百的varchar列,在dynamic格式下它们都是保存在offpage的,也即是不与数据行保存在统一页,而是保存在特定的其余页面中,云云读取这些字段还需求拜候更多的数据页。道理以下图,这边不开展细讲了。
底细上dynamic格式下,关于长度大于40字节的字段都是云云保存的。纵然查问请求这些列的时刻,这类字段越多,查问履行效率越低,因而交易的查问语句不要老是select*,希奇是在表的列中有良多这类大字段(varchar,blob,text)的时刻,而是针对性地取舍需求的列,云云能够防止innodb从无谓地掏出这些字段,要懂得掏出这些字段每个行均大概需求补充屡屡磁盘IO操纵,希奇是它们的页面保存效率原本就较量低。在理论保存一行的时刻并不是一齐云云的字段都邑offpage保存,而是从长到短次第掏出做offpage保存,直到行的长度达标(也即是一页存最少两行)。云云的话,行的长度仍是大概会较量长,纵然最大长度在40以上的varchar列较量多的话。innodb的页与行的大概布局以下图:本例顶用户碰到的题目是由于innodb_page_size=4k,因而这个表的最大大概的行长度超过了4k页面答应的最大长度(略少于2k)。而办理的措施囊括:1.拆分表,以交易需求为基本,依据ER模子的界说来拆分,同时最佳把根基静态的列放在一个表中,常常被革新的放在另一个表中。2.纵然交易需求请求必然在这个表中界说这么多列,那末把最大长度少于40字节的(本例凑巧哄骗的是UTF8)列挑一些能够收缩的,收缩直到能够胜利建表为止。
预览时标签弗成点收录于合集#个