MySQL的索引是什么
MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。 打个比方:如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的 MySQL就是一个人力三轮车。 索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不 是组合索引。组合索引,即一个索引包含多个列。
剖析MySQL InnoDB引擎的行锁表锁,怎样利用锁解决事务并发问题
从 MySQL 5.7 开始,开发人员改变了 InnoDB 构建二级索引的,采用自下而上的方法,而不是早期版本中自上而下的方法了。在这篇文章中,我们将通过一个示例来说明如何构建 InnoDB 索引。最后,我将解释如何通过为 innodb_fill_factor 设置更合适的值。索引构建过程在有数据的表上构建索引,InnoDB 中有以下几个阶段:1.读取阶段(从聚簇索引读取并构建二级索引条目)2.合并排序阶段3.插入阶段(将排序记录插入二级索引)在 5.6 版本之前,MySQL 通过一次插入一条记录来构建二级索引。这是一种“自上而下”的方法。搜索插入位置从树的根部(顶部)开始并达到叶页(底部)。该记录插入光标指向的叶页上。在查找插入位置和进行业面拆分和合并方面开销很大。从MySQL 5.7开始,添加索引期间的插入阶段使用“排序索引构建”,也称为“批量索引加载”。在这种方法中,索引是“自下而上”构建的。即叶页(底部)首先构建,然后非叶级别直到根(顶部)。示例在这些情况下使用排序的索引构建:ALTER TABLE t1 ADD INDEX(or CREATE INDEX)ALTER TABLE t1 ADD FULLTEXT INDEXALTER TABLE t1 ADD COLUMN, ALGORITHM = INPLACEOPIMIZE t1对于最后两个用例,ALTER 会创建一个中间表。中间表索引(主要和次要)使用“排序索引构建”构建。算法在 0 级别创建页,还要为此页创建一个游标使用 0 级别处的游标插入页面,直到填满页面填满后,创建一个兄弟页(不要插入到兄弟页)为当前的整页创建节点指针(子页中的最小键,子页码),并将节点指针插入上一级(父页)在较高级别,检查游标是否已定位。如果没有,请为该级别创建父页和游标在父页插入节点指针如果父页已填满,请重复步骤 3, 4, 5, 6现在插入兄弟页并使游标指向兄弟页在所有插入的末尾,每个级别的游标指向最右边的页。提交所有游标(意味着提交修改页面的迷你事务,释放所有锁存器)为简单起见,上述算法跳过了有关压缩页和 BLOB(外部存储的 BLOB)处理的细节。通过自下而上的构建索引为简单起见,假设子页和非子页中允许的 最大记录数为 3CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c BLOB);INSERT INTO t1 VALUES (1, 11, 'hello111');INSERT INTO t1 VALUES (2, 22, 'hello222');INSERT INTO t1 VALUES (3, 33, 'hello333');INSERT INTO t1 VALUES (4, 44, 'hello444');INSERT INTO t1 VALUES (5, 55, 'hello555');INSERT INTO t1 VALUES (6, 66, 'hello666');INSERT INTO t1 VALUES (7, 77, 'hello777');INSERT INTO t1 VALUES (8, 88, 'hello888');INSERT INTO t1 VALUES (9, 99, 'hello999');INSERT INTO t1 VALUES (10, 1010, 'hello101010');ALTER TABLE t1 ADD INDEX k1(b);InnoDB 将主键字段追加到二级索引。二级索引 k1 的记录格式为(b, a)。在排序阶段完成后,记录为:(11,1), (22,2), (33,3), (44,4), (55,5), (66,6), (77,7), (88,8), (99,9), (1010, 10)初始插入阶段让我们从记录 (11,1) 开始。在 0 级别(叶级别)创建页创建一个到页的游标所有插入都将转到此页面,直到它填满了箭头显示游标当前指向的位置。它目前位于第 5 页,下一个插入将转到此页面。还有两个空闲插槽,因此插入记录 (22,2) 和 (33,3) 非常简单对于下一条记录 (44,4),页码 5 已满(前面提到的假设最大记录数为 3)。这就是步骤。页填充时的索引构建创建一个兄弟页,页码 6不要插入兄弟页在游标处提交页面,即迷你事务提交,释放锁存器等作为提交的一部分,创建节点指针并将其插入到 【当前级别 + 1】 的父页面中(即在 1 级别)节点指针的格式 (子页面中的最小键,子页码) 。第 5 页的最小键是 (11,1) 。在父级别插入记录 ((11,1),5)。1 级别的父页尚不存在,MySQL 创建页码 7 和指向页码 7 的游标。将 ((11,1),5) 插入第 7 页现在,返回到 0 级并创建从第 5 页到第 6 页的链接,反之亦然0 级别的游标现在指向兄弟页,页码为 6将 (44,4) 插入第 6 页下一个插入 - (55,5) 和 (66,6) - 很简单,它们转到第 6 页。插入记录 (77,7) 类似于 (44,4),除了父页面 (页面编号 7) 已经存在并且它有两个以上记录的空间。首先将节点指针 ((44,4),8) 插入第 7 页,然后将 (77,7) 记录到同级 8 页中。插入记录 (88,8) 和 (99,9) 很简单,因为第 8 页有两个空闲插槽。下一个插入 (1010,10) 。将节点指针 ((77,7),8) 插入 1级别的父页(页码 7)。MySQL 在 0 级创建同级页码 9。将记录 (1010,10) 插入第 9 页并将光标更改为此页面。以此类推。在上面的示例中,数据库在 0 级别提交到第 9 页,在 1 级别提交到第 7 页。我们现在有了一个完整的 B+-tree 索引,它是自下至上构建的!索引填充因子全局变量 innodb_fill_factor 用于设置插入 B-tree 页中的空间量。默认值为 100,表示使用整个业面(不包括页眉)。聚簇索引具有 innodb_fill_factor=100 的免除项。 在这种情况下,聚簇索引也空间的 1 /16 保持空闲。即 6.25% 的空间用于未来的 DML。值 80 意味着 MySQL 使用了 80% 的页空间填充,预留 20% 于未来的更新。如果 innodb_fill_factor=100 则没有剩余空间供未来插入二级索引。如果在添加索引后,期望表上有更多的 DML,则可能导致业面拆分并再次合并。在这种情况下,建议使用 80-90 之间的值。此变量还会影响使用 OPTIMIZE TABLE 和 ALTER TABLE DROP COLUMN, ALGOITHM=INPLACE 重新创建的索引。也不应该设置太低的值,例如低于 50。因为索引会占用浪费更多的磁盘空间,值较低时,索引中的页数较多,索引统计信息的采样可能不是最佳的。优化器可以选择具有次优统计信息的错误查询计划。排序索引构建的优点没有页面拆分(不包括压缩表)和合并没有重复搜索插入位置插入不会被重做记录(页分配除外),因此重做日志子系统的压力较小缺点ALTER 正在进行时,插入性能降低 Bug#82940,但在后续版本中计划修复。
千万级MYSQL数据单表搜索重复结果统计优化问题
Hi~ 高手们!
Facebook用户量十分庞大,为什么还使用MySQL数据库
尽管Facebook使用MySQL,但它们并不是一成不变的使用它。 事实上,他们的团队已经提交了许多MySQL核心和Innodb插件的高性能增强。 他们的主要重点是增加性能计数器到Innodb。 其他更改集中在IO子系统上,包括以下新功能:1 innodb_io_capacity:设置服务器的IO容量以确定后台IO的速率限制2 innodb_read_io_threads, innodb_write_io_threads:设置后台IO线程3 innodb_max_merged_io:设置可能合并到一个大IO请求中的相邻IO请求的最大数量Facebook使用MySQL作为键值存储,其中数据随机分布在一大组逻辑实例中。 这些逻辑实例分散在物理节点之间,负载均衡在物理节点级完成。 Facebook已经开发了一个分区方案,其中全局ID被分配给所有的用户数据。 他们也有一个自定义的归档方案,它基于每个用户的频繁和最近的数据。 大部分数据是随机分布的。 令人惊讶的是,据传Facebook有1800个MySQL服务器,但只有3个全职DBAFacebook主要将MySQL用于结构化数据存储,例如墙贴,用户信息等。这些数据在各个数据中心之间复制。 对于blob存储(照片,视频等),Facebook使用一个自定义的解决方案,涉及外部的CDN和内部的NFS同样重要的是,Facebook大量使用Memcache,这是一种内存缓存系统,通过在RAM中缓存数据和对象来加速动态数据库驱动的网站,以减少阅读时间。 Memcache是Facebook的主要缓存形式,大大减少了数据库的负载。 拥有一个缓存系统可以使Facebook的速度与调用数据一样快。 如果不需要访问数据库,则只需根据用户标识从缓存中获取数据所以,“Facebook使用什么数据库”似乎是一个简单的问题,你可以看到他们已经添加了各种其他系统,使其真正的具有网络可扩展性。 但是,仍然可以自由地使用这样一个观点:“MySQL和Oracle或者MS SQL Server一样好或者更好,因为就算只有Facebook使用它,它也有5亿用户!”
PostgreSQL与MySQL相比,优势何在
如果把Oracle DBA转到PostgreSQL数据库上是比较容易的,毕竟PostgreSQL数据库与Oracle数据库很相似。PostgreSQL几乎支持所有的SQL标准,支持类型相当丰富。PostgreSQL数据库的源代码要比MySQL数据库的源代码更容易读懂,如果团队的C语言能力比较强的话,就可以在PostgreSQL数据库上做开发,比方说实现类似greenplum的系统,这样也能与现在的分布式趋势接轨。为了说明PostgreSQL的功能,下面从“从Oracle迁移到Mysql之前必须知道的50件事”简要对比一下PostgreSQL数据库与MySQL数据库之间的差异。从Oracle迁移到Mysql会面对的50件难事1、对子查询的优化表现不佳。(PostgreSQL可解决)2、 对复杂查询的处理较弱。(PostgreSQL可解决)3、 查询优化器不够成熟。(PostgreSQL可解决)PostgreSQL完全支持SQL-92标准,对SQL的支持也很全面,可以支持复杂的SQL查询。4、 性能优化工具与度量信息不足。(PostgreSQL可解决)PostgreSQL提供了执行计划和详细的cost值,可以方便看到SQL的执行效率。5、 审计功能相对较弱。6、 安全功能不成熟,没有用户组与角色的概念,没有回收权限的功能(仅可以授予权限)。当一个用户从不同的主机/网络以同样的用户名/密码登录之后,可能被当作完全不同的用户来处理,没有类似于Oracle的内置的加密功能。7、 身份验证功能是完全内置的,不支持LDAP、Active Directory或其它类似的外部身份验证功能。8、 Mysql Cluster可能与你想象的有较大差异。9、 存储过程与触发器的功能有限。(PostgreSQL可解决)PostgreSQL提供了完善的存储过程和触发器支持。10、 垂直扩展性较弱。11、 不支持MPP(大规模并行处理)。(PostgreSQL可解决)PostgreSQL是类似Oracle数据库的多进程架构,而不像MySQL是多线程的架构,所以能支持MPP。12、 支持SMP(对称多处理器),但是如果每个处理器超过4或8个核(core)时,Mysql的扩展性表现较差。13、 对于时间、日期、间隔等时间类型没有秒以下级别的存储类型。14、 可用来编写存储过程、触发器、计划事件以及存储函数的语言功能较弱。15、 没有基于回滚(roll-back)的恢复功能,只有前滚(roll-forward)的恢复功能。16、 不支持快照功能。17、 不支持数据库链(database link)。有一种叫做Federated的存储引擎可以作为一个中转将查询语句传递到远程服务器的一个表上,不过,它功能很粗糙并且漏洞很多。18、 数据完整性检查非常薄弱,即使是基本的完整性约束,也往往不能执行。(PostgreSQL可解决)PostgreSQL提供完善的数据完整性检查机制,支持外键。19、 优化查询语句执行计划的优化器提示非常少。20、 只有一种表连接类型:嵌套循环连接(nested-loop),不支持排序-合并连接(sort-merge join)与散列连接(hash join)。(PostgreSQL可解决)PostgreSQL则支持这些表连接类型。21、 大部分查询只能使用表上的单一索引;在某些情况下,会存在使用多个索引的查询,但是查询优化器通常会低估其成本,它们常常比表扫描还要慢。(PostgreSQL可解决)PostgreSQL数据不存在这个问题,假设表T的两个字段col1的col2上有两个索引,idx_1和idx_2,那么select * from t where col1=:a and col2=:b;查询时,PostgreSQL数据库有可能把这个查询转化为select * from t where col1=:a intersect select * from t where col2=:b,这样两个索引都可以使用上。22、不支持位图索引(bitmap index)。每种存储引擎都支持不同类型的索引。大部分存储引擎都支持B-Tree索引。23、 管理工具较少,功能也不够成熟。24、没有成熟能够令人满意的IDE工具与调试程序。可能不得不在文本编辑器中编写存储过程,并且通过往表(调试日志表)中插入记录的来做调试。25、 每个表都可以使用一种不同的存储引擎。(PostgreSQL可解决)26、 每个存储引擎在行为表现、特性以及功能上都可能有很大差异。(PostgreSQL可解决)27、大部分存储引擎都不支持外键。(PostgreSQL可解决)28、默认的存储引擎(MyISAM)不支持事务,并且很容易损坏。(PostgreSQL可解决)29、最先进最流行的存储引擎InnoDB由Oracle拥有。(PostgreSQL可解决)30、有些执行计划只支持特定的存储引擎。特定类型的Count查询,在这种存储引擎中执行很快,在另外一种存储引擎中可能会很慢。(PostgreSQL可解决)PostgreSQL只有一种存储引擎,所以不存在上面的情况。而PostgreSQL支持完善的事务。31、执行计划并不是全局共享的,,仅仅在连接内部是共享的。32、全文搜索功能有限, 只适用于非事务性存储引擎。 Ditto用于地理信息系统/空间类型和查询。(PostgreSQL可解决)PostgreSQL数据库支持全文搜索,支持更多类型的索引,如B-tree,R-tree, Hash, GiST, GIN,R-tree,GIST,GIN索引可用于空间类型和查询。33、没有资源控制。一个完全未经授权的用户可以毫不费力地耗尽服务器的所有内存并使其崩溃,或者可以耗尽所有CPU资源。34、没有集成商业智能(business intelligence), OLAP **数据集等软件包。35、 没有与Grid Control类似的工具36、 没有类似于RAC的功能。如果你问”如何使用Mysql来构造RAC”,只能说你问错了问题。37、不支持用户自定义类型或域(domain)。(PostgreSQL可解决)PostgreSQL支持丰富的类型,同时也支持自定义类型。38、 每个查询支持的连接的数量最大为61。39、MySQL支持的SQL语法(ANSI SQL标准)的很小一部分。不支持递归查询、通用表表达式(Oracle的with 语句)或者窗口函数(分析函数)。支持部分类似于Merge或者类似特性的SQL语法扩展,不过相对于Oracle来讲功能非常简单。(PostgreSQL可解决)这些PostgreSQL数据库都支持,如窗口函数。40、不支持功能列(基于计算或者表达式的列,Oracle11g 开始支持计算列,以及早期版本就支持虚列(rownum,rowid))。41、不支持函数索引,只能创建基于具体列的索引。(PostgreSQL可解决)PostgreSQL支持函数索引。42、不支持物化视图。43、不同的存储引擎之间,统计信息差别很大,并且所有的存储引擎支持的统计信息都只支持简单的基数(cardinality)与一定范围内的记录数(rows-in-a-range)。 换句话说,数据分布统计信息是有限的。更新统计信息的机制也不多。44、没有内置的负载均衡与故障切换机制。45、 复制(Replication)功能是异步的,并且有很大的局限性。例如,它是单线程的(single-threaded),因此一个处理能力更强的Slave的恢复速度也很难跟上处理能力相对较慢的Master。46、 Cluster并不如想象的那么完美。或许我已经提过这一点,但是这一点值得再说一遍。47、数据字典(INFORMATION_SCHEMA)功能很有限,并且访问速度很慢(在繁忙的系统上还很容易发生崩溃)。48、不支持在线的Alter Table操作。49、 不支持Sequence。(PostgreSQL可解决)PostgreSQL支持sequence。50、 类似于ALTER TABLE或CREATE TABLE一类的操作都是非事务性的。它们会提交未提交的事务,并且不能回滚也不能做灾难恢复。Schame被保存在文件系统上,这一点与它使用的存储引擎无关。(PostgreSQL可解决)PostgreSQL不存在这个问题。每种数据库都有不同的应用场景PostgreSQL具备了更高的可靠性,对数据一致性、完整性的支持高于MySQL,因此PostgreSQL更加适合严格的企业应用场景,MySQL查询速度较快,更适合业务逻辑相对简单、数据可靠性要求较低的互联网场景。以上个人浅见,欢迎批评指正。认同我的看法,请点个赞再走,感谢!喜欢我的,请关注我,再次感谢!