摘要:MySQL一张表最多能存多少数据?
本文分享自华为云社区《为什么MySQL单表不能超过2000万行?》,作者: GaussDB 数据库 。
最近看到一篇《我说MySQL每张表最好不要超过2000万数据,面试官让我回去等通知》的文章,非常有趣。
文中提到,他朋友在面试的过程中说,自己的工作就是把用户操作信息存到MySQL里,因为数据量超大(5000万条左右),需要每天定时生成3张表,然后将数据取模分别存到这三张表里。
下面是两人的对话:
面试后续暂且不论,不过,互联网江湖上的确流传着一个说法:单表数据量超过500万行时就要进行分表分库,已经超过2000万行时MySQL的性能就会急剧下降。
那么,MySQL一张表最多能存多少数据?
今天我们就从技术层面剖析一下,MySQL单表数据不能过大的根本原因是什么?
很多人认为:数据量超过500万行或2000万行时,引起B+tree的高度增加,延长了索引的搜索路径,进而导致了性能下降。事实果真如此吗?
我们先理一下关系,MySQL采用了索引组织表的形式组织数据,叶子节点存储数据,非叶子节点存储主键与页面号的映射关系。若用户的主键长度是8字节时,MySQL中页面偏移占4个字节,在非叶子节点的时候实际上是8+4=12个字节,12个字节表示一个页面的映射关系。
MySQL默认是16K的页面,抛开它的配置header,大概就是15K,因此,非叶子节点的索引页面可放15*1024/12=1280条数据,按照每行1K计算,每个叶子节点可以存15条数据。同理,三层就是15*1280*1280=24576000条数据。只有数据量达到24576000条时,深度才会增加为4,所以,索引深度没有那么容易增加,详细数据可参考下表:
搜索路径延长导致性能下降的说法,与当时的机械硬盘和内存条件不无关系。
之前机械硬盘的IOPS在100左右,而现在普遍使用的SSD的IOPS已经过万,之前的内存最大几十G,现在服务器内存最大可达到TB级。
因此,即使深度增加,以目前的硬件资源,IO也不会成为限制MySQL单表数据量的根本性因素。
那么,限制MySQL单表不能过大的根本性因素是什么?
我们可以尝试从MySQL所采用的存储引擎InnoDB本身来探究一下。
大家知道InnoDB引擎使用的是索引组织表,它是通过索引来组织数据的,而它采用B+tree作为索引的数据结构。
B+Tree操作非原子,所以当一个线程做结构调整(SMO,Struction-Modification-Operation)时一般会涉及多个节点的改动。
SMO动作过程中,此时若有另一个线程进来可能会访问到错误的B+Tree结构,InnoDB为了解决这个问题采用了乐观锁和悲观锁的并发控制协议。
InnoDB对于叶子节点的修改操作如下:
对根节点加S锁(shared lock,叫共享锁,也称读锁),依次对非叶子节点加S锁。
如果叶子节点的修改不会引起B+Tree结构变动,如分裂、合并等操作,那么只需要对叶子节点进行加X锁(exclusive lock,叫排他锁,也称为写锁)即可完成修改。如下图中所示 :
如果对叶子结点的修改会触发SMO,那么会采用悲观锁的方式。
采用悲观锁,需要重新遍历B+Tree,对根节点加全局SX锁(SX锁是行锁),然后从根节点到叶子节点可能修改的节点加X锁。
在整个SMO过程中,根节点始终持有SX锁(SX锁表示有意向修改这个保护的范围,SX锁与SX锁、X锁冲突,与S锁不冲突),此时其他的SMO则需要等待。
因此,InnoDB对于简单的主键查询比较快,因为数据都存储在叶子节点中,但对于数据量大且改操作比较多的TP型业务,并发会有很严重的瓶颈问题。
在对叶子节点的修改操作中,InnoDB可以实现较好的1与1、1与2的并发,但是无法解决2的并发。因为在方式2中,根节点始终持有SX锁,必须串行执行,等待上一个SMO操作完成。这样在具有大量的SMO操作时,InnoDB的B+Tree实现就会出现很严重的性能瓶颈。
目前业界有一个更好的方案B-Link Tree,与B+Tree相比,B-Link Tree优化了B+Tree结构调整时的锁粒度,只需要逐层加锁,无需对root节点加全局锁。因此,可以做到在SMO过程中写操作的并发执行,保持高并发下性能的稳定。
B-Link Tree主要改进点有2个:
1.中间节点增加link指针,指向右兄弟节点;
2.每个节点内增加字段high key,存储该节点中最大的key值。
新增的link指针是为了解决SMO过程中并发写的问题,在SMO过程中,B-Link Tree对修改节点逐层加锁,修改完一层即可放锁,然后去加上一层节点的锁继续修改。这样在InnoDB引擎中被SMO阻塞的写操作可以有机会在SMO操作过程中并发进行。
如下图所示,在节点2分裂为节点2和4的过程中,只需要在最后一步将父节点1指向新节点4时,对父节点1加锁,其他操作均无需对父节点加锁,更无需对root节点加锁,因此,大大提升了SMO过程中写操作的并发度。
由此可见,与B+Tree全局加锁对比,B-Link Tree在高并发操作下的性能是显著优于B+Tree的。GaussDB当前采用的就是B-Link Tree索引数据结构。
索引组织表的叶子节点,存储主键以及应对行的数据,InnoDB默认页面为16K,若每行数据的大小为1000字节,每个叶子节点仅能存储16行数据。
在索引组织表中,当叶子节点的扇出值过低时,SMO的触发将更加频繁,进而放大了SMO无法并发写的缺陷。
目前业界有一个堆组织表的数据组织方案,也是华为云数据库GaussDB采用的方案。它的叶子节点存储索引键以及对应的行指针(所在的页面编号及页内偏移),堆组织表叶子节点可以存更多的数据,分析可得在同样的数据量与业务并发量下,堆组织表会比索引组织表发生SMO概率低许多。
在8U32G的两台服务器分别搭建了MySQL(B+Tree和索引组织表)与GaussDB(B-Link Tree和堆组织表)的环境,进行了如下性能验证:
实验场景:在基础表的场景上,测试增量随机插入性能。
1.基础表总大小10G,包含主键随机分布的1000w行数据,每行数据1k;
2.插入主键随机分布的1000w行数据,每行数据大小1k,测试并发插入性能。
结论:随着并发数的上升,GaussDB能稳步提升系统的TPS,而MySQL并发数的提高并不能带来TPS的显著提升。
综上所述,MySQL无法支持大数据量下并发修改的根本原因,是由于其索引并发控制协议的缺陷造成的,而MySQL选择索引组织表,又放大了这一缺陷。所以,开源MySQL数据库更适用于主键查询为主的简单业务场景,如互联网类应用,对于复杂的商业场景限制比较明显。
相比之下 ,采用B-Link Tree和堆组织表的GaussDB数据库在性能和场景应用方面更胜一筹。
点击关注,第一时间了解华为云新鲜技术~
工作来源UsenixSecurity 2021工作背景在合法网站植入暗链推广非法商品/服务(如毒品、色情、赌博等)是很常见的,黑帽SEO是其中一个主要的途径。搜索引擎为此付出了巨大的努力,Google每年针对黑帽SEO会更新排名算法超过500次。SEO旨在提高网站、*搜索引擎的检索排名,而黑帽SEO通常通过植入暗链的方式提高排名。黑帽SEO也引入了StealthyDefacement技术,在网页中选择对排名有影响的位置进行微小的修改。这样不仅难以被发现,还可以优化搜索引擎排名。与此同时,非法网站的推广者也和使用者也合谋使用同义关键字(行业黑话)躲避检测。搜索引擎有义务对检索结果进行审查和筛选,非法的服务和敏感的个人信息都可以根据请求被删除或者自动剔除。攻击者可以通过行业黑话来规避检测,例如使用M4RKSIX指代六台彩。而使用者发现关键词被屏蔽后,就会尝试其他行业黑话进行检索,行业黑话通常是谐音或者形似。使用者可以直接访问或者被重定向进行访问。黑产会使用多种黑帽SEO技术:Keywordstuffing:网页包含关键字数量对页面排名很重要,将关键词与非法网站关联起来Linkfarm:入侵
在App中使用地图定位十分常见,购物功能的可以直接定位当前位置,发动态功能可以定位当前位置发出,社交功能可以定位周边用户等等。这里我使用高德地图定位当前位置并显示地址和经纬度。github代码传送门先上效果图:实现步骤:1.创建应用获取key:接入第三方无一例外,去高德地图官网注册账号并创建应用。填入包名和keystore的Sha1。创建应用获取Sha1,输入命令keytool-v-list-keystorekeystore文件路径,我在这里通过控制台获取调试版的:进入.android目录cd.android复制输入命令获取keytool-v-list-keystoredebug.keystore复制过程截图:创建完成获取Key:2.接入SDK添加定位库compile'com.amap.api:location:latest.integration'复制添加2D地图库compile'com.amap.api:map2d:latest.integration'复制添加地图权限:<uses-permissionandroid:name=&quo
在OOP程序设计中,当定义一个class的时候,可从某个现有的class继承 新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Baseclass、Superclass) 格式: class子类名(父类名): pass复制使用示例classAnimal(object): defrun(self): print('Animalisrunning...') classDog(Animal): pass classDog1(Animal): defrun(self): print('Dogisrunning...') defrun_twice(animal): animal.run() animal.run() dog=Dog() dog.run()#输出:Animalisrunning... dog1=Dog1() dog1.run()#输出:Dogisrunning...,执行子类自己的方法 run_twice(Animal()) #输出:Animalisrunning... #输出:A
文章来源:探码科技据赛迪顾问统计,在技术领域中最近10,000条专利中常见的关键词中,数据采集、存储介质、海量数据、分布式成为技术领域最热词汇。其中,数据采集是提到最多的词汇。数据采集是进行大数据分析的前提也是必要条件,在整个数据利用流程中占据重要地位。数据采集方式分为三种:系统日志采集法、网络数据采集法以及其他数据采集法。随着Web2.0的发展,整个Web系统涵盖了大量的价值化数据,目前针对Web系统的数据采集通常通过网络爬虫来实现,本文将对网络数据和网络爬虫进行系统描述。什么是网络数据网络数据,是指非传统数据源,例如通过抓取搜索引擎获得的不同形式的数据。网络数据也可以是从数据聚合商或搜索引擎网站购买的数据,用于改善目标营销。这种类型的数据可以是结构化的,也可以是非结构化的(更有可能的),可以由网络链接,文本数据,数据表,图像,视频等组成。 网络构成了当今提供给我们的大部分数据,根据许多研究可知,非结构化数据占据了其中的80%。尽管这些形式的数据较早被忽略了,但是竞争加剧以及需要更多数据的需求使得必须使用尽可能多的数据源。网络数据可以用来干什么互联网拥有数十亿页的数据,网络数据作为潜
本文转载自数据管道最近入手了一个用户画像的项目,这里面真的“坑”满多的,你肯定很想问,不就是用户画像嘛,会这么烦吗?现在可能就需要拆分成几个问题来做这个项目。 用户画像是什么? 用户画像,又称人群画像,是根据用户人口统计学信息(自身属性)、社交关系、偏好习惯和消费行为等信息而抽象出来的标签化画像。怎么做用户画像 构建用户画像的核心工作即是给用户贴“标签”。啥是“标签”?对某一类特定群体或对象的某项特征进行抽象分类或者概括。然后你可能会得到这样一张图:(图片参考于网络,侵权联系即删) 这里面“标签”是根据用户的行为数据直接得到,部分是通过一系列算法或规则挖掘得到。直接得到的数据比较好理解,比如用户在网站或APP上主动填写和上传的数据,严格一些平台(比如电商平台)会要求用户上传身份证、学生证、驾驶证、银行卡等,这样的数据准确性就较高。因此毫无疑问阿里、京东、腾讯在用户基础数据的准确性上甩百度几条街(有独自的用户标识账号,比如你的那一串微信号数字,淘宝账号,京东账号)。关于标签准确性你是不是会想到几家公司?没错,移动、联通、电信三大运营商的标签体系先天性的准确到可怕。为什么会这样讲,首先办理
1.前言转眼间已经毕业3年了,从13年工作算起也算是工作5年多了,期间做过android、flex、c#、前端偏js、Java、半运维。最终还是选择了曾经最讨厌的Java。 在现在这份工作之前,给别人的感觉我就是跳槽频繁。说实话,如果一份工作在薪水和体现你能力之间有个相对权衡的点,相信都不会想着跳槽的,毕竟一个新的环境一个新的坑,你能不能像在之前公司被器重都是未知数。 在此写下本人的一些感触。 2.感悟个人认为当一个程序员工作年限在3年+的时候,2.1对于java程序员:如果没有接触过线上的各种事故和OOM问题、sql优化、性能优化、jstack、jvisualvm等jvm监控工具的使用,而是仅仅写curd,或ctrl+cctrl+v那么你就要好反思下差距了,现在学习这些还不晚。2.2对于前端偏js:这里不说具体的技术,仅仅谈论通用性。当你写代码的时候,有没有考虑过网络请求的io、js代码执行的效率加密压缩、网页加载速度、localstorage等h5新特性的使用。如果没有,请此刻注意下你的代码。2.3代码规范:对于程序员来说,我认为你只有代码写的很规范才算是一个优秀程序员的开始,应该
千平发自凹非寺 量子位出品|公众号QbitAICM,在安卓刷机世界大名鼎鼎。这是一个基于安卓修改进化的手机操作系统,以无广告、无预装、模块化、可玩性高而闻名,国内不少安卓手机操作系统,都曾借鉴CM系统。当年CM的目标一度是“干掉”Google的原生安卓系统,按照他们的计划,2020年将有5亿部手机运行CM系统。不过去年12月底,这杆安卓世界的大旗突然倒下。CM背后的Cyanogen公司宣布终止这个项目。如今10个月过去,这家公司的主要人马卷土重来。转行无人车据文风异常简洁的axios网站报道,Cyanogen那帮人搞了一个新公司,名叫Cyngn。不过他们不是要继续未竟的事业,而是悄悄地转行了……他们的新方向是:无人车。这家新公司还处于秘密状态,仅有零星信息被披露出来。包括Cyngn宣称将为自主机器和车辆提供“创新解决方案”;现任CEO是LiorTal也就是之前的COO,原来的CEO离职创业去了。高峰时期,Cyanogen有大约150名员工,而如今的Cyngn只有大约30名员工,不过其中包括来自奔驰和Udacity的汽车工程师,来自LinkedIn的信息显示,这家公司正在大肆招人。另据《
1、^ 符 ---代表一行的开始"category".match(/^cat/);//返回以c开头的紧接一个a,紧接一个t的文本数组!复制2、$ 符 ---代表一行的结束alert("category".match(/ry$/));//返回以y结尾,紧接着前面一个是r的文本数组输出:ry复制3、[........] 表示字符组用于匹配一串字符如果我们需要搜索的单词是"gray",同时又不确定他是否写作"gray",这个时候就可以使用正则表达式结构体-[........]-字符组。他允许使用者在字符组内列出希望匹配的字符.e表示匹配字符e,a表示匹配字符a,[ea]则表示能匹配a或者e,所以要匹配"gray"可以这样写:gr[ea]y,表示先找到一个g,紧接着一个r,然后是一个e或者a,紧接这最后一个是y。注意:字符组中的内部的匹配情况,与外部的不一样,他表示的是或.alert("gray".match(/^gr[ae]y/));//返回以g开头,紧接着是一
数据流DataInputStream和DataOutputStream介绍数据流:用来操作基本数据类型和字符串的DataInputStream:将文件中存储的基本数据类型和字符串写入内存的变量中DataOutputStream:将内存中的基本数据类型和字符串的变量写出文件中利用DataOutputStream向外写出变量:publicclassTest01{ //这是一个main方法,是程序的入口: publicstaticvoidmain(String[]args)throwsIOException{ //DataOutputStream:将内存中的基本数据类型和字符串的变量写出文件中 /*Filef=newFile("d:\\Demo2.txt"); FileOutputStreamfos=newFileOutputStream(f); DataOutputStreamdos=newDataOutputStream(fos);*/ DataOutputStreamdos=newDataOutputStream(newFileOutputStream(newFi
昨天生产突然反馈上传的结果查询出现了乱码,我赶紧打开后台数据库,发现果真有数据变成了乱码。这个上传程序都运行3个多月了,从未发生乱码现象,查看程序的运行日志,发现日志里的中文都变成了乱码,然后对比之前和现在的上传文件,发现了问题,之前文件格式是ANSI,现在变成了UTF8 然后直接上网搜索解决方法,方法如下: usingSystem; usingSystem.IO; usingSystem.Text; ///<summary> ///FileEncoding的摘要说明 ///</summary> namespaceFileEncoding { ///<summary> ///获取文件的编码格式 ///</summary> publicclassEncodingType { ///<summary> ///给定文件的路径,读取文件的二进制数据,判断文件的编码类型 ///</summary> ///<paramname=“FILE_NAME“>文件路径</param> ///
转载请标明出处:http://www.cnblogs.com/zblade/ 本文参照unity官网上对于assetBundle的一系列讲解,主要针对assetbundle的知识点做一个梳理笔记,也为后续的资源打包设计做一个基础学习,本文的代码和图片均来自unity官网,详情可以查看Unity的DOCUMENTATION。 一、什么是AssetBundle AssetBundle就像一个ZIP压缩文件,里面存储着不同平台的特殊资源(models/texture/prefabs/materials/audioclip/scenes...),这些资源都可以在运行时进行加载。具体的assetBundle中主要包含什么?主要包含两种互相关联的东西: 1.磁盘上的文件:也就是assetbundle文档,可以将其视为一个容器或者文件夹,其中包含两类文件:序列化文件和资源文件,序列化文件就是资源在打包后对应的各个平台的序列化操作后的文件,资源文件主要是针对textures/audio等较大的文件打包的二进制文件,这类文件在加载的时候是在其他线程执行的(效率更高)。 2.就是实际的assetb
1、if语句if语句基本用法: if表达式: 语句块复制 其中,表达式可以是一个单纯的布尔值或变量,也可以是比较表达式或逻辑表达式,如果表达式为真,则执行“语句块”;如果表达式的值为假,就跳过“语句块”,继续执行后面的语句。 2、if…else语句if…else语句基本用法: if表达式: 语句块1 else: 语句块2复制 使用if…else语句时,表达式可以是一个单纯的布尔值或变量,也可以是比较表达式或逻辑表达式,如果满足条件,则执行if后面的语句块,否则,执行else后面的语句块。在使用else语句时,else一定不可以单独使用,它必须和保留字if一起使用。 3、if…elif…else语句if…elif…else语句基本用法: if表达式1: 语句块1 elif表达式2: 语句块2 elif表达式3: 语句块3 … else: 语句块n复制 使用if…elif…else语句时,表达式可以是一个单纯的布尔值或变量,也可以是比较表达式或逻辑表达式,如果表达式为真,执行语句;而如果表达式为假,则跳过该语句,进行下一个elif的判断
常用sql操作如下: 1.查看当前数据库的所有表 showtables; 2.创建表 createtablestu(sidint,snamechar(20),sageintdefault20); 3.查看表的创建信息 showcreatetablestu; 4.查看表的字段信息 descstu; 5.添加字段 altertablestuaddgenderchar(4); 6.删除字段 altertablestudropgender; 7.修改某个字段的数据类型 altertablestumodifysnamevarchar(20); 8.修改某个字段的名和数据类型 altertablestuchangesidsnumbersmallint; 9.查询数据(记录)初体验 select*fromstu; 10.插入数据(记录) insertintostuvalues(1,"tom",20); insertintostu(snumber,sname)values(2,"jack); insertintostuvalues(3,"jane",18)
packagecom.jeesite.modules.jiQiao.web;importcom.google.common.base.Supplier;importcom.jeesite.modules.jiQiao.entity.Person;importcom.jeesite.modules.jiQiao.entity.UserTest;importjava.util.function.Function;publicclassDemoFunctionTest{//对象转换,如把String转成int,A类转成B类publicstaticvoidmain(String[]args){/*getNumber((Stringstr)->{Integerinteger=Integer.valueOf(str);inti=Integer.parseInt(str);returninteger;});*///把一个数值转换成int并且乘5/*getNumber2((Stringstr)->{returnInteger.parseInt(str);},(Integeri)->{
1.STP(SpanningTreeProtocol生成树协议)的技术背景: 1)关于环路: 例如,下面三个交换机互相连接,可能会导致环路(数据包从lsw1-lsw2-lsw3-lsw1-lsw2-...,一直发停不下来) 路由器有避免环路的机制,例如ttl,最大转发16次后丢包; 但交换机没有这种机制; STP技术就是用来避免交换机环路的; 2)二层网络设计的需求和问题: 为了提高可靠性,交换机之间会通过多条链路相连,从而避免单点故障。 但也会带来一些致命的环路问题。 如图: 可靠性差的网络拓扑结构; 当一条链路故障,或交换机故障时,会导致单点故障,也就是其下面的网络全部瘫痪; 为了提高可靠性、避免单点故障的产生,通常在设计拓扑图时,会添加一个冗余的交换机; 当其中一条链路挂掉后,另外一条还能继续使用,网络不会瘫痪; 但这
历届试题矩阵翻硬币 时间限制:1.0s 内存限制:256.0MB 问题描述 小明先把硬币摆成了一个n行m列的矩阵。 随后,小明对每一个硬币分别进行一次Q操作。 对第x行第y列的硬币进行Q操作的定义:将所有第i*x行,第j*y列的硬币进行翻转。 其中i和j为任意使操作可行的正整数,行号和列号都是从1开始。 当小明对所有硬币都进行了一次Q操作后,他发现了一个奇迹——所有硬币均为正面朝上。 小明想知道最开始有多少枚硬币是反面朝上的。于是,他向他的好朋友小M寻求帮助。 聪明的小M告诉小明,只需要对所有硬币再进行一次Q操作,即可恢复到最开始的状态。然而小明很懒,不愿意照做。于是小明希望你给出他更好的方法。帮他计算出答案。 输入格式 输入数据包含一行,两个正整数nm,含义见题目描述。 输出格式 输出一个正整数,表示最开始有多少枚硬币是反面朝上的。 样例输入 23 样例输出 1 数据规模和约定 对于10%的数据,n、m<=10^3; 对于20%的数据,n、m<=10^7; 对于40%的数据,n、m<=10^15;
整理: board_init_f---->init_sequence_f---->5.8timer_init---->5.9get_clocks---->5.11init_baud_rate---->5.12serial_init---->5.20dram_init---->5.21testdram---->5.22DRAM空间的分配---->5.23setup_dram_configboard_init_f---->init_sequence_r---->6)board_init---->10)board_early_init_r---->11)arch_early_init_r---->12)power_init_board---->21)board_late_init 1.前言 书接上文(u-boot启动流程分析(1)_平台相关部分),本文介绍u-boot启动流程中和具体版型(board)有关的部分,也即board_init_f/board_init_r所代表的、board有关
记忆化:就是将中间的运算结果保存起来,避免多次计算 #include<bits/stdc++.h> usingnamespacestd; constint32_tMAX_N=1e6; constint32_tKEEP_N=5*1e7; int32_tkeep[KEEP_N+5]; int32_tGetChainLength(int64_tx) { int32_tans=0; if(x==1)return1; if(x<=KEEP_N&&keep[x]!=0)returnkeep[x]; if(x%1==1) { ans=GetChainLength(3*x+1)+1; } else { ans=GetChainLength(x>>1)+1; } if(x<=KEEP_N)keep[x]=ans; returnans; } intmain() { int32_tnum=1; for(int32_ti=2;i<=MAX_N;i++) { if(GetChainLength(i)>GetChainLength(num))num
jmeter新版本插件管理器下载地址:https://jmeter-plugins.org/install/Install/ 将jar包放入libext目录下,重启jmeter。 示例按装服务器监控插件: 打开jmeter,选择options下的pluginsManager: InstalledPlugins:已安装的插件 AvailablePlugins:可下载的插件 Upgrades:可更新的插件 选择: 然后点击安装即可。 循环控制器: 1、永远选项:勾选上这一项表示一直循环下去 2、如果同时设置了线程组的循环次数和循环控制器的循环次数,那循环控制器的下面的接口运行的次数为两个数值相乘的结果。 添加路径:线程组->添加->逻辑控制器->循环控制器 ps:如果是英文版的jmeter,ThreadGroup->add->logicController->LoopController 仅一次控制器: 将仅一次控制器作为循环控制器的