精华内容
下载资源
问答
  • 表空间相关1、表空间和数据文件的关系: 表空间一个个数据文件组成;数据文件的大小和位置可以自己定义;2、表空间的分类: 永久表空间:数据库中要永久化存储的一些对象,如:表、视图、存储过程 临时表空间:...

    概述

    oracle表空间这个概念大家应该都很熟悉了, 这是一个逻辑概念,可以理解为在数据库中开辟的空间用来存储数据库对象。

    e0566997d78274072d5ebf7d2c019921.png

    表空间相关

    1、表空间和数据文件的关系:

    表空间由一个或多个数据文件组成;数据文件的大小和位置可以自己定义;

    2、表空间的分类:

    永久表空间:数据库中要永久化存储的一些对象,如:表、视图、存储过程

    临时表空间:数据库操作当中中间执行的过程,执行结束后,存放的内容会被自动释放

    UNDO表空间:用于保存事务所修改数据的旧值,可以进行数据的回滚

    篇幅有限,下面主要对系统表空间、辅助表空间和临时表空间做个介绍。


    一、系统表空间

    SYSTEM 表空间是 Oracle 数据库最重要的一个表空间,存放了一些 DDL 语言产生的 信息以及 PL/SQL 包、视图、函数、过程等,称之为数据字典,因此该表空间也具有其特殊性。

    Oracle服务器使用SYSTEM表空间管理整个数据库。这个表空间包含系统的数据字典和关于数据库的管理信息,这些信息均包含在SYS方案中,只有SYS用户或者拥有所需权限的其它管理用户才可访问这些信息。SYSTEM表空间用于核心功能(例如数据字典表)。

    1、建议不存放用户数据

    //为数据库设定默认表空间

    SQL>ALTER DATABASE DEFAULTTABLESPACE tablespace_name;

    //查询默认表空间

    SQL> select property_name,property_value from database_properties where property_name like 'DEFAULT%';

    94bdab20afa8803a981ffec2c5e6c9bb.png

    2、SYSTEM表空间特性

    • 不能脱机 offline

    • 不能置为只读 read only

    • 不能重命名

    • 不能删除

    3、空间管理

    这里一定要保证空间可用,一般存放单个数据文件,如果 SYSTEM 表空间数据文件很大,可以考虑使用 bigfile。


    二、辅助表空间

    SYSAUX 表空间在 Oracle Database 10g 中引入,作为 SYSTEM 表空间的辅助表空间.

    以前一些使用独立表空间或系统表空间的数据库组件现在在 SYSAUX 表空间中创建. 通过分离这些组件和功能,SYSTEM 表空间的负荷得以减轻.反复创建一些相关对象及组件 引起 SYSTEM 表空间的碎片问题得以避免。

    SYSTEM和SYSAUX表空间是在创建数据库时创建的必须存在的表空间。这些表空间必须联机。在OPEN状态下,SYSAUX表空间可以脱机以执行表空间恢复,而SYSTEM表空间则不能,这两种表空间都不能设置为只读状态。在MOUNT状态下,任何表空间都可以脱机。

    SYSTEM表空间的大小一般变化不大,而SYSAUX表空间在默认条件下如果不做任何配置,那么随着时间的推移,会越来越大。所以,如果SYSAUX表空间过大,那么应该及时诊断清理该表空间。

    对于SYSTEM表空间而言,如果占用过大,那么一般情况下是由于审计表(SYS.AUD$)过大引起的。需要将审计表移动到其它表空间中,然后再清理审计表(TRUNCATE TABLE SYS.AUD$)即可。需要注意的是,如果审计表过大,那么应该分部去清理审计表。

    对于SYSAUX表空间而言,如果占用过大,那么一般情况下是由于AWR信息或对象统计信息没有及时清理引起的,具体原因可以通过如下的SQL语句查询:

    SELECT OCCUPANT_NAME "Item
    展开全文
  • 表空间相关1、表空间和数据文件的关系: 表空间一个个数据文件组成;数据文件的大小和位置可以自己定义;2、表空间的分类: 永久表空间:数据库中要永久化存储的一些对象,如:表、视图、存储过程 临时表空间:...

    概述

    oracle表空间这个概念大家应该都很熟悉了, 这是一个逻辑概念,可以理解为在数据库中开辟的空间用来存储数据库对象。

    bd8e131f7c87a53da123cb5c5d33cc42.png

    表空间相关

    1、表空间和数据文件的关系:

    表空间由一个或多个数据文件组成;数据文件的大小和位置可以自己定义;

    2、表空间的分类:

    永久表空间:数据库中要永久化存储的一些对象,如:表、视图、存储过程

    临时表空间:数据库操作当中中间执行的过程,执行结束后,存放的内容会被自动释放

    UNDO表空间:用于保存事务所修改数据的旧值,可以进行数据的回滚

    篇幅有限,下面主要对系统表空间、辅助表空间和临时表空间做个介绍。


    一、系统表空间

    SYSTEM 表空间是 Oracle 数据库最重要的一个表空间,存放了一些 DDL 语言产生的 信息以及 PL/SQL 包、视图、函数、过程等,称之为数据字典,因此该表空间也具有其特殊性。

    Oracle服务器使用SYSTEM表空间管理整个数据库。这个表空间包含系统的数据字典和关于数据库的管理信息,这些信息均包含在SYS方案中,只有SYS用户或者拥有所需权限的其它管理用户才可访问这些信息。SYSTEM表空间用于核心功能(例如数据字典表)。

    1、建议不存放用户数据

    //为数据库设定默认表空间

    SQL>ALTER DATABASE DEFAULTTABLESPACE tablespace_name;

    //查询默认表空间

    SQL> select property_name,property_value from database_properties where property_name like 'DEFAULT%';

    70d8d1e0a3c60909172119d41caf8c8c.png

    2、SYSTEM表空间特性

    • 不能脱机 offline

    • 不能置为只读 read only

    • 不能重命名

    • 不能删除

    3、空间管理

    这里一定要保证空间可用,一般存放单个数据文件,如果 SYSTEM 表空间数据文件很大,可以考虑使用 bigfile。


    二、辅助表空间

    SYSAUX 表空间在 Oracle Database 10g 中引入,作为 SYSTEM 表空间的辅助表空间.

    以前一些使用独立表空间或系统表空间的数据库组件现在在 SYSAUX 表空间中创建. 通过分离这些组件和功能,SYSTEM 表空间的负荷得以减轻.反复创建一些相关对象及组件 引起 SYSTEM 表空间的碎片问题得以避免。

    SYSTEM和SYSAUX表空间是在创建数据库时创建的必须存在的表空间。这些表空间必须联机。在OPEN状态下,SYSAUX表空间可以脱机以执行表空间恢复,而SYSTEM表空间则不能,这两种表空间都不能设置为只读状态。在MOUNT状态下,任何表空间都可以脱机。

    SYSTEM表空间的大小一般变化不大,而SYSAUX表空间在默认条件下如果不做任何配置,那么随着时间的推移,会越来越大。所以,如果SYSAUX表空间过大,那么应该及时诊断清理该表空间。

    对于SYSTEM表空间而言,如果占用过大,那么一般情况下是由于审计表(SYS.AUD$)过大引起的。需要将审计表移动到其它表空间中,然后再清理审计表(TRUNCATE TABLE SYS.AUD$)即可。需要注意的是,如果审计表过大,那么应该分部去清理审计表。

    对于SYSAUX表空间而言,如果占用过大,那么一般情况下是由于AWR信息或对象统计信息没有及时清理引起的,具体原因可以通过如下的SQL语句查询:

    SELECT OCCUPANT_NAME "Item
    展开全文
  • 否则不要开始就考虑拆分,拆分会带来逻辑、部署、运维的各种复杂度,一般以整型值为主的在千万级以下,字符串为主的在五百万以下是没有太问题的。而事实上很时候 MySQL 单的性能依然有不少优化空间,...

    当MySQL单表记录数过大时,增删改查性能都会急剧下降

    单表优化

    除非单表数据未来会一直不断上涨,否则不要一开始就考虑拆分,拆分会带来逻辑、部署、运维的各种复杂度,一般以整型值为主的表在千万级以下,字符串为主的表在五百万以下是没有太大问题的。

    而事实上很多时候 MySQL 单表的性能依然有不少优化空间,甚至能正常支撑千万级以上的数据量。

    字段

    • 尽量使用 TINYINT、 SMALLINT、 MEDIUM_INT 作为整数类型而非 INT,如果非负则加上 UNSIGNED
    • VARCHAR 的长度只分配真正需要的空间
    • 使用枚举或整数代替字符串类型
    • 尽量使用 TIMESTAMP 而非 DATETIME
    • 单表不要有太多字段,建议在 20 以内
    • 避免使用 NULL 字段,很难查询优化且占用额外索引空间
    • 用整型来存 IP

    索引

    • 索引并不是越多越好,要根据查询有针对性的创建,考虑在 WHERE 和 ORDER BY
    • 命令上涉及的列建立索引,可根据 EXPLAIN 来查看是否用了索引还是全表扫描
    • 应尽量避免在 WHERE 子句中对字段进行 NULL 值判断,否则将导致引擎放弃使用索引而进行全表扫描
    • 值分布很稀少的字段不适合建索引,例如"性别"这种只有两三个值的字段
    • 字符字段只建前缀索引
    • 字符字段最好不要做主键
    • 不用外键,由程序保证约束
    • 尽量不用 UNIQUE,由程序保证约束
    • 使用多列索引时主意顺序和查询条件保持一致,同时删除不必要的单列索引

    查询SQL

    • 可通过开启慢查询日志来找出较慢的 SQL
    • 不做列运算:SELECT id WHERE age+1=10,任何对列的操作都将导致表扫描,它包括数据库教程函数、计算表达式等等,查询时要尽可能将操作移至等号右边
    • sql 语句尽可能简单:一条 sql 只能在一个 cpu 运算;大语句拆小语句,减少锁时间;一条大sql 可以堵死整个库
    • 不用 SELECT *
    • OR 改写成 IN:OR 的效率是 n 级别, IN 的效率是 log(n) 级别,IN 的个数建议控制在 200 以内
    • 不用函数和触发器,在应用程序实现
    • 避免 %xxx 式查询
    • 少用 JOIN
    • 使用同类型进行比较,比如用 '123' 和 '123' 比, 123 和 123 比
    • 尽量避免在 WHERE 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描
    • 对于连续数值,使用 BETWEEN 不用 IN:SELECT id FROM t WHERE num BETWEEN 1 AND 5
    • 列表数据不要拿全表,要使用 LIMIT 来分页,每页数量也不要太大

    引擎

    目前广泛使用的是 MyISAM 和 InnoDB 两种引擎:

    MyISAM

    MyISAM 引擎是 MySQL 5.1 及之前版本的默认引擎,它的特点是:

    • 不支持行锁,读取时对需要读到的所有表加锁,写入时则对表加排它锁
    • 不支持事务
    • 不支持外键
    • 不支持崩溃后的安全恢复
    • 在表有读取查询的同时,支持往表中插入新纪录
    • 支持 BLOB 和 TEXT 的前 500 个字符索引,支持全文索引
    • 支持延迟更新索引,极大提升写入性能
    • 对于不会进行修改的表,支持压缩表,极大减少磁盘空间占用

    InnoDB

    InnoDB 在 MySQL 5.5 后成为默认索引,它的特点是:

    • 支持行锁,采用 MVCC 来支持高并发
    • 支持事务
    • 支持外键
    • 支持崩溃后的安全恢复
    • 不支持全文索引(5.6.4之后版本逐渐开始支持)

    总体来讲,MyISAM 适合 SELECT 密集型的表,而 InnoDB 适合 INSERT 和 UPDATE 密集型的表

    系统调优参数

    可以使用下面几个工具来做基准测试:

    • sysbench:一个模块化,跨平台以及多线程的性能测试工具
    • iibench-mysql:基于 Java 的 MySQL/Percona/MariaDB 索引进行插入性能测试工具
    • tpcc-mysql:Percona 开发的 TPC-C 测试工具

    具体的调优参数内容较多,具体可参考官方文档,这里介绍一些比较重要的参数:

    • backlog:backlog 值指出在 MySQL 暂时停止回答新请求之前的短时间内多少个请求可以被存在堆栈中。也就是说,如果 MySql 的连接数据达到 maxconnections 时,新来的请求将会被存在堆栈中,以等待某一连接释放资源,该堆栈的数量即 backlog,如果等待连接的数量超过back_log,将不被授予连接资源。可以从默认的 50 升至 500
    • wait_timeout:数据库连接闲置时间,闲置连接会占用内存资源。可以从默认的 8 小时减到半小时
    • maxuserconnection:最大连接数,默认为 0 无上限,最好设一个合理上限
    • thread_concurrency:并发线程数,设为 CPU 核数的两倍
    • skipnameresolve:禁止对外部连接进行 DNS 解析,消除 DNS 解析时间,但需要所有远程主机用 IP 访问
    • keybuffersize:索引块的缓存大小,增加会提升索引处理速度,对 MyISAM 表性能影响最大。对于内存 4G 左右,可设为 256M 或 384M,通过查询 show status like'key_read%',保证 key_reads / key_read_requests 在 0.1% 以下最好
    • innodbbufferpool_size:缓存数据块和索引块,对 InnoDB 表性能影响最大。通过查询 show status like'Innodb_buffer_pool_read%',保证 (Innodb_buffer_pool_read_requests –
      Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests 越高越好
    • innodbadditionalmempoolsize:InnoDB 存储引擎用来存放数据字典信息以及一些内部数据结构的内存空间大小,当数据库对象非常多的时候,适当调整该参数的大小以确保所有数据都能存放在内存中提高访问效率,当过小的时候,MySQL 会记录 Warning 信息到数据库的错误日志中,这时就需要该调整这个参数大小
    • innodblogbuffer_size:InnoDB 存储引擎的事务日志所使用的缓冲区,一般来说不建议超过
      32MB
    • querycachesize:缓存 MySQL 中的 ResultSet,也就是一条 SQL 语句执行的结果集,所以仅仅只能针对 select 语句。当某个表的数据有任何任何变化,都会导致所有引用了该表的select 语句在 Query Cache 中的缓存数据失效。所以,当我们的数据变化非常频繁的情况下,使用 Query Cache 可能会得不偿失。根据命中率 (Qcache_hits / (Qcache_hits + Qcache_inserts) * 100)) 进行调整,一般不建议太大,256MB 可能已经差不多了,大型的配置型静态数据可适当调大. 可以通过命令 show status like'Qcache_%' 查看目前系统 Query Catch 使用大小
    • readbuffersize:MySql 读入缓冲区大小。对表进行顺序扫描的请求将分配一个读入缓冲区,MySql 会为它分配一段内存缓冲区。如果对表的顺序扫描请求非常频繁,可以通过增加该变量值以及内存缓冲区大小提高其性能
    • sortbuffersize:MySql 执行排序使用的缓冲大小。如果想要增加 ORDER BY 的速度,首先看是否可以让 MySQL 使用索引而不是额外的排序阶段。如果不能,可以尝试增加 sortbuffersize 变量的大小
    • readrndbuffer_size:MySql 的随机读缓冲区大小。当按任意顺序读取行时(例如,按照排序顺序),将分配一个随机读缓存区。进行排序查询时,MySql 会首先扫描一遍该缓冲,以避免磁盘搜索,提高查询速度,如果需要排序大量数据,可适当调高该值。但 MySql 会为每个客户连接发放该缓冲空间,所以应尽量适当设置该值,以避免内存开销过大
    • record_buffer:每个进行一个顺序扫描的线程为其扫描的每张表分配这个大小的一个缓冲区。如果你做很多顺序扫描,可能想要增加该值
      threadcachesize:保存当前没有与连接关联但是准备为后面新的连接服务的线程,可以快速响应连接的线程请求而无需创建新的
    • tablecache:类似于 threadcache_size,但用来缓存表文件,对 InnoDB 效果不大,主要用于 MyISAM

    升级硬件

    Scale up,这个不多说了,根据 MySQL 是 CPU 密集型还是 I/O 密集型,通过提升 CPU 和内存、使用 SSD,都能显著提升 MySQL 性能。

    读写分离

    也是目前常用的优化,从库读主库写,一般不要采用双主或多主引入很多复杂性,尽量采用文中的其他方案来提高性能。
    同时目前很多拆分的解决方案同时也兼顾考虑了读写分离。

    缓存

    缓存可以发生在这些层次:

    • MySQL 内部:在系统调优参数介绍了相关设置
    • 数据访问层:比如 MyBatis 针对 SQL 语句做缓存,而 Hibernate 可以精确到单个记录,这里缓存的对象主要是持久化对象 PersistenceObject
    • 应用服务层:这里可以通过编程手段对缓存做到更精准的控制和更多的实现策略,这里缓存的对象是数据传输对象 DataTransferObject(DTO)
    • Web 层:针对 web 页面做缓存
    • 浏览器客户端:用户端的缓存

    可以根据实际情况在一个层次或多个层次结合加入缓存。缓存扩展:缓存常见问题及解决方案
    这里重点介绍下服务层的缓存实现,目前主要有两种方式:

    • 直写式(Write Through):在数据写入数据库后,同时更新缓存,维持数据库与缓存的一致性。这也是当前大多数应用缓存框架如 Spring Cache 的工作方式。这种实现非常简单,同步好,但效率一般。
    • 回写式(Write Back):当有数据要写入数据库时,只会更新缓存,然后异步批量的将缓存数据同步到数据库上。这种实现比较复杂,需要较多的应用逻辑,同时可能会产生数据库与缓存的不同步,但效率非常高。

    表分区

    MySQL 在 5.1 版引入的分区是一种简单的水平拆分,用户需要在建表的时候加上分区参数,对应用是透明的无需修改代码
    对用户来说,分区表是一个独立的逻辑表,但是底层由多个物理子表组成,实现分区的代码实际上是通过对一组底层表的对象封装,但对 SQL 层来说是一个完全封装底层的黑盒子。MySQL 实现分区的方式也意味着索引也是按照分区的子表定义,没有全局索引。

    cae8a480836c7484fd82cb53c95dc7bd.png

    用户的 SQL 语句是需要针对分区表做优化,SQL 条件中要带上分区条件的列,从而使查询定位到少量的分区上,否则就会扫描全部分区,可以通过 EXPLAIN PARTITIONS 来查看某条SQL 语句会落在那些分区上,从而进行 SQL 优化,如下图 5 条记录落在两个分区上:

    d83b5697002356cab51b9ec8d59dd2ed.png

    分区的好处是:

    • 可以让单表存储更多的数据
    • 分区表的数据更容易维护,可以通过清楚整个分区批量删除大量数据,也可以增加新的分区来支持新插入的数据。另外,还可以对一个独立- - 分区进行优化、检查、修复等操作
    • 部分查询能够从查询条件确定只落在少数分区上,速度会很快
    • 分区表的数据还可以分布在不同的物理设备上,从而高效利用多个硬件设备
    • 可以使用分区表赖避免某些特殊瓶颈,例如 InnoDB 单个索引的互斥访问、ext3 文件系统的
    1. 锁竞争
    • 可以备份和恢复单个分区

    分区的限制和缺点:

    • 一个表最多只能有 1024 个分区
    • 如果分区字段中有主键或者唯一索引的列,那么所有主键列和唯一索引列都必须包含进来
    • 分区表无法使用外键约束
    • NULL 值会使分区过滤无效
    • 所有分区必须使用相同的存储引擎

    分区的类型:

    • RANGE 分区:基于属于一个给定连续区间的列值,把多行分配给分区
    • LIST 分区:类似于按 RANGE 分区,区别在于 LIST 分区是基于列值匹配一个离散值集合中的某个值来进行选择
    • HASH 分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含 MySQL 中有效的、产生非负整数值的任何表达式
    • KEY 分区:类似于按 HASH 分区,区别在于 KEY 分区只支持计算一列或多列,且 MySQL 服务器提供其自身的哈希函数。必须有一列或多列包含整数值

    分区适合的场景有:

    最适合的场景数据的时间序列性比较强,则可以按时间来分区,如下所示:

    8956b7306bf75215276e3f40f6ba2e54.png

    查询时加上时间范围条件效率会非常高,同时对于不需要的历史数据能很容的批量删除。
    如果数据有明显的热点,而且除了这部分数据,其他数据很少被访问到,那么可以将热点数据单独放在一个分区,让这个分区的数据能够有机会都缓存在内存中,查询时只访问一个很小的分区表,能够有效使用索引和缓存。索引相关:带你从头到尾捋一遍MySQL索引
    另外 MySQL 有一种早期的简单的分区实现 - 合并表(merge table),限制较多且缺乏优化,不建议使用,应该用新的分区机制来替代

    垂直拆分

    垂直分库是根据数据库里面的数据表的相关性进行拆分。扩展:互联网公司常用分库分表方案汇总
    比如:一个数据库里面既存在用户数据,又存在订单数据,那么垂直拆分可以把用户数据放到用户库、把订单数据放到订单库。

    垂直分表是对数据表进行垂直拆分的一种方式,常见的是把一个多字段的大表按常用字段和非常用字段进行拆分,每个表里面的数据记录数一般情况下是相同的,只是字段不一样,使用主键关联
    比如原始的用户表是:

    039e48a6398cdcbc6aa4bf6a7d23eead.png

    垂直拆分的优点是:

    • 可以使得行数据变小,一个数据块( Block )就能存放更多的数据,在查询时就会减少 I/O 次数(每次查询时读取的 Block 就少)
    • 可以达到最大化利用 Cache 的目的,具体在垂直拆分的时候可以将不常变的字段放一起,将经常改变的放一起
    • 数据维护简单

    缺点是:

    • 主键出现冗余,需要管理冗余列
    • 会引起表连接 JOIN 操作(增加 CPU 开销)可以通过在业务服务器上进行 join 来减少数据库压力
    • 依然存在单表数据量过大的问题(需要水平拆分)
    • 事务处理复杂

    水平拆分

    概述

    水平拆分是通过某种策略将数据分片来存储,分库内分表和分库两部分,每片数据会分散到不同的 MySQL 表或库,达到分布式的效果,能够支持非常大的数据量。前面的表分区本质上也是一种特殊的库内分表。

    库内分表,仅仅是单纯的解决了单一表数据过大的问题,由于没有把表的数据分布到不同的机器上,因此对于减轻 MySQL 服务器的压力来说,并没有太大的作用,大家还是竞争同一个物理机上的 IO、CPU、网络,这个就要通过分库来解决
    前面垂直拆分的用户表如果进行水平拆分,结果是:

    d5bf0e410a8996f6c855fe9f15a93baa.png

    实际情况中往往会是垂直拆分和水平拆分的结合,即将 Users_A_M 和 Users_N_Z 再拆成 Users 和 UserExtras,这样一共四张表
    水平拆分的优点是:

    • 不存在单库大数据和高并发的性能瓶颈
    • 应用端改造较少
    • 提高了系统的稳定性和负载能力

    缺点是:

    • 分片事务一致性难以解决
    • 跨节点 Join 性能差,逻辑复杂
    • 数据多次扩展难度跟维护量极大

    分片原则

    • 能不分就不分,参考单表优化
    • 分片数量尽量少,分片尽量均匀分布在多个数据结点上,因为一个查询 SQL 跨分片越多,则总体性能越差,虽然要好于所有数据在一个分片的结果,只在必要的时候进行扩容,增加分片数量
    • 分片规则需要慎重选择做好提前规划,分片规则的选择,需要考虑数据的增长模式,数据的访问模式,分片关联性问题,以及分片扩容问题,最近的分片策略为范围分片,枚举分片,一致性 Hash 分片,这几种分片都有利于扩容
    • 尽量不要在一个事务中的 SQL 跨越多个分片,分布式事务一直是个不好处理的问题
    • 查询条件尽量优化,尽量避免 Select * 的方式,大量数据结果集下,会消耗大量带宽和
      CPU 资源,查询尽量避免返回大量结果集,并且尽量为频繁使用的查询语句建立索引。
    • 通过数据冗余和表分区依赖降低跨库 Join 的可能

    这里特别强调一下分片规则的选择问题,如果某个表的数据有明显的时间特征,比如订单、交易记录等,则他们通常比较合适用时间范围分片,因为具有时效性的数据,我们往往关注其近期的数据,查询条件中往往带有时间字段进行过滤,比较好的方案是,当前活跃的数据,采用跨度比较短的时间段进行分片,而历史性的数据,则采用比较长的跨度存储。

    总体上来说,分片的选择是取决于最频繁的查询 SQL 的条件,因为不带任何 Where 语句的查询 SQL,会遍历所有的分片,性能相对最差,因此这种 SQL 越多,对系统的影响越大,所以我们要尽量避免这种 SQL 的产生。

    解决方案

    由于水平拆分牵涉的逻辑比较复杂,当前也有了不少比较成熟的解决方案。这些方案分为两大类:

    • 客户端架构
    • 代理架构

    客户端架构

    通过修改数据访问层,如 JDBC、Data Source、MyBatis,通过配置来管理多个数据源,直连数据库,并在模块内完成数据的分片整合,一般以 Jar 包的方式呈现
    这是一个客户端架构的例子:

    9d98fc6e5599afd0b7fe9b68a0f45209.png

    可以看到分片的实现是和应用服务器在一起的,通过修改 Spring JDBC 层来实现

    客户端架构的优点是:

    • 应用直连数据库,降低外围系统依赖所带来的宕机风险
    • 集成成本低,无需额外运维的组件

    缺点是:

    • 限于只能在数据库访问层上做文章,扩展性一般,对于比较复杂的系统可能会力不从心
    • 将分片逻辑的压力放在应用服务器上,造成额外风险

    代理架构

    通过独立的中间件来统一管理所有数据源和数据分片整合,后端数据库集群对前端应用程序透明,需要独立部署和运维代理组件
    这是一个代理架构的例子:

    通过独立的中间件来统一管理所有数据源和数据分片整合,后端数据库集群对前端应用程序透明,需要独立部署和运维代理组件
    这是一个代理架构的例子:

    58ac9412c4801c8e76505effe61b39f9.png

    代理组件为了分流和防止单点,一般以集群形式存在,同时可能需要 Zookeeper 之类的服务组件来管理

    代理架构的优点是:

    • 能够处理非常复杂的需求,不受数据库访问层原来实现的限制,扩展性强
    • 对于应用服务器透明且没有增加任何额外负载

    缺点是:

    • 需部署和运维独立的代理中间件,成本高
    • 应用需经过代理来连接数据库,网络上多了一跳,性能有损失且有额外风险

    各方案比较

    a25a025afc1a981d9a084ca8f2926267.png

    如此多的方案,如何进行选择?可以按以下思路来考虑:

    • 确定是使用代理架构还是客户端架构。中小型规模或是比较简单的场景倾向于选择客户端架构,复杂场景或大规模系统倾向选择代理架构
    • 具体功能是否满足,比如需要跨节点 ORDER BY,那么支持该功能的优先考虑
    • 不考虑一年内没有更新的产品,说明开发停滞,甚至无人维护和技术支持
    • 最好按大公司 -> 社区 -> 小公司 -> 个人这样的出品方顺序来选择
    • 选择口碑较好的,比如 GitHub 星数、使用者数量质量和使用者反馈
    • 开源的优先,往往项目有特殊需求可能需要改动源代码

    按照上述思路,推荐以下选择:

    • 客户端架构:ShardingJDBC
    • 代理架构:MyCat 或 Atlas

    兼容 MySQL 且可水平扩展的数据库

    目前也有一些开源数据库兼容 MySQL 协议,如:

    ce7f524fc35dd22549c295cde66c323b.png

    NoSQL

    在 MySQL 上做 Sharding 是一种戴着镣铐的跳舞,事实上很多大表本身对 MySQL 这种RDBMS 的需求并不大,并不要求 ACID,可以考虑将这些表迁移到 NoSQL,彻底解决水平扩展问题,例如:

    • 日志类、监控类、统计类数据
    • 非结构化或弱结构化数据
    • 对事务要求不强,且无太多关联操作的数据

    转载自云栖社区,侵删

    展开全文
  • Java—实现一个顺序

    2021-04-01 00:33:55
    静态顺序的定长数组导致N定了,空间了浪费,开少了不够用. 相比之下动态顺序更灵活, 根据需要动态的分配空间大小. 2.实现一个顺序 首先定义顺序的属性和构造方法: 顺序的底层是一个数组,所以需要...

    Java—实现一个顺序表

    1.顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。

    顺序表一般可以分为:
    静态顺序表:使用定长数组存储。
    动态顺序表:使用动态开辟的数组存储

    静态顺序表适用于确定知道需要存多少数据的场景.
    静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用.
    相比之下动态顺序表更灵活, 根据需要动态的分配空间大小.

    2.实现一个顺序表

    1.首先定义顺序表的属性和构造方法:
    顺序表的底层是一个数组,所以需要一个数组和一个定义数组中有效数字的属性,并提供构造方法,在构造方法中可以设置参数。
    在这里插入图片描述

    public class MyArrayList {
        //顺序表所需要的属性;
        public int[] elem;//引用类型默认为空
        public int usedSize;//不给初始化,默认为0
    
        //提供构造方法
        public MyArrayList() {//无参数的构造方法
    
            this.elem = new int[6];
        }
    
        public MyArrayList(int capacity) {//有参数的构造方法
            this.elem = new int[capacity];
    
        }
    

    2.实现一些操作:
    1、新增元素

    // 在 pos 位置新增元素
        public void add(int pos, int data) {
            if(isFull()){
                //System.out.println("顺序表为满");
                resize();
                //return;
            }
            if(pos <0 || pos >this.usedSize){
                System.out.println("pos位置不合法");
            }
            //代码走这说明满足条件,插入
            for (int i =usedSize-1; i >= pos ; i--) {
                this.elem[i+1] = this.elem[i];//数据从后挪;
            }
            this.elem[pos] = data;
            usedSize++;//重新记录有效数字
        }
        public void add2(int data){
            if(isFull()){
                //System.out.println("顺序表为满");
                resize();
                //return;
            }
            this.elem[usedSize]=data;
            usedSize++;//重新记录有效数字
        }
    

    2、是否包含某个元素

    // 判定是否包含某个元素
        public boolean contains(int toFind) {
            for (int i = 0; i <usedSize ; i++) {
                if(this.elem[i] == toFind ){
                    return true;
                }
            }
            return false;
        }
    

    3、查找某个元素对应的位置

    // 查找某个元素对应的位置
        public int search(int toFind) {
            for (int i = 0; i <usedSize ; i++) {
                if(this.elem[i] == toFind ){
                    return i;
                }
            }
            return -1;
        }
    

    4、获取 pos 位置的元素

    // 获取 pos 位置的元素
        public int getPos(int pos) {
            if(pos<0 || pos>=usedSize){
                return -1;
            }
            for (int i = 0; i <usedSize ; i++) {
                if(i==pos){
                    return this.elem[i];
                }
            }
            return -1;
        }
    

    5、 给 pos 位置的元素设为 value

    // 给 pos 位置的元素设为 value
        public void setPos(int pos, int value) {
            //判断pos的值是否合法
            if( pos<0 || pos>=usedSize ){
                return;
            }
            //找到pos;
            for (int i = 0; i <usedSize ; i++) {
                if(i==pos){
                    this.elem[i]=value;
                }
            }
        }
    

    6、打印顺序表

    // 打印顺序表
        public void display() {
            for (int i = 0; i < usedSize; i++) {
                System.out.print(this.elem[i]+" ");
            }
            System.out.println();
        }
    

    7、判断数组是否为满

     public boolean isFull(){//判断数组是否为满
            if(this.usedSize == elem.length){
                return true;
            }
            return false;
    }
    

    8、扩容操作

      public void resize(){//扩容操作
            this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
        }
    

    9、删除第一次出现的关键字key
    在这里插入图片描述

    // 删除第一次出现的关键字key
        public void remove(int key) {
            //1、查找是否有key  index
            int index = search(key);
            if(index == -1) {
                System.out.println("没有找到");
                return;
            }
            //找到之后i = index;    i < usdSize-1
            for(int i = index;i < this.usedSize-1;i++) {
                this.elem[i] = this.elem[i+1];
            }
            //3、this.usedSize--;
            this.usedSize--;//长度减小
    
        }
    

    10、获取顺序表长度

    // 获取顺序表长度
        public int size() {
            return usedSize;
        }
    

    11、清空顺序表

    // 清空顺序表
        public void clear() {
            this.usedSize = 0;
        }
    

    测试类代码:

    public class TestDemo {
        public static void main(String[] args) {
            MyArrayList myArrayList =new MyArrayList();//有参数
            //myArrayList.add3(123);
            //myArrayList.add3(124);
            //MyArrayList myArrayList1 = new MyArrayList(20);//无参数
            myArrayList.add(0,12);
            myArrayList.add(1,22);
            myArrayList.add(2,32);
            myArrayList.add(3,42);
            myArrayList.add2(123);
            myArrayList.add2(124);
            myArrayList.display();
            System.out.println("===========");
    
            int ret = myArrayList.usedSize;
            System.out.println(ret);
            System.out.println("========");
            System.out.println(myArrayList.contains(12));
            System.out.println("==========");
            System.out.println(myArrayList.search(12));
            System.out.println("==========");
            myArrayList.remove(32);
            myArrayList.display();
            System.out.println("=========");
            System.out.println(myArrayList.getPos(2));
            System.out.println("========");
            myArrayList.setPos(0,10);
            myArrayList.display();
    
    
        }
    }
    

    结果截图:
    在这里插入图片描述
    顺序表的缺点:

    1. 顺序表中间/头部的插入删除,时间复杂度为O(N)
    2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
    3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。
    展开全文
  • 优化除非单数据未来会一直不断上涨,否则不要开始就考虑拆分,拆分会带来逻辑、部署、运维的各种复杂度,一般以整型值为主的在千万级以下,字符串为主的在五百万以下是没有太问题的。而事实上很时候...
  • Oracle创建用户与授予表空间与权限

    万次阅读 2018-09-15 16:33:40
    一个数据库可以有个表空间,一个表空间里可以有个表。表空间就是存个表的物理空间; 可以指定表空间的大小位置等。 建立表空间的定义 建立表空间(一般建N个存数据的表空间和一个索引空间): create ...
  • oracle数据库表空间

    2013-04-24 17:16:32
    1.基本概念: oracle的逻辑结构一般可以分成:表空间(tablespace)、段(segment)、区(extent)、数据块(data block)...2)表空间由一个或个数据文件在物理上构成,一个数据文件只能属于一个表空间,这里通过数据文件位
  • 表空间设计

    2013-10-22 09:55:22
    Oracle数据库开创性地提出了表空间的设计理念,这为Oracle...1、一般的表或索引单独分配一个tablespace。 2、Read only对象或Read mostly对象分成一组,存在对应的tablespace中。 3、若tablespace中的对象皆是
  • 哈希)——哈希的大小

    万次阅读 多人点赞 2018-08-30 13:47:27
    哈希的设计主要是为了查找,...哈希的长度一般是定长的,在存储数据之前我们应该知道我们存储的数据规模是多大,应该尽可能地避免频繁地让哈希扩容。但是如果设计的太大,那么就会浪费空间,因为我们跟不用不...
  • 共享表空间:Innodb的所有数据保存在一个单独的表空间里面,而这个表空间可以由很个文件组成,一个表可以跨个文件存在,所以其大小限制不再是文件大小的限制,而是其自身的限制 ,innodb官方显示表空间的最大...
  • 关键词:板对板连接器,连接...在电子制造中,整个设备可能需要适合可用的空间,因为,如果电路板设计阶段的PCB 倾向于占用太多空间,则该器件可能被分成两或更多个板。板对板连接器可以在板之间连接电源和信号以...
  • Oracle 表空间设计

    千次阅读 2013-10-19 17:19:41
    Oracle数据库开创性地提出了表空间的设计理念,这为Oracle...1、一般的表或索引单独分配一个tablespace。 2、Read only对象或Read mostly对象分成一组,存在对应的tablespace中。 3、若tablespace中的对象皆是
  • oracle表空间和锁问题

    2021-04-29 21:54:34
    一般情况下使用oracle,不会出现的问题,但是超出一定的临界会出现一些问题,这里就记录了工作中遇到的问题:表被锁了和表空间不足了的问题。 问题描述: 第一个是表被锁的情况,如果只是简单的单次查询,插入是...
  • 近期排查了一个数据库job执行异常,表现为: insert操作失败,目标表里没有数据(与一般经验一致); 但目标占用的空间持续增长,且不正常的增速(没数据,空间还快速消耗,与一般经验不符)。 通过排查原因是:...
  • ...·共享表空间:Innodb的所有数据保存在一个单独的表空间里面,而这个表空间可以由很个文件组成,一个表可以跨个文件存在。  所以其大小限制不再是文件大小的限制,而是其自身的限制...
  • ·共享表空间:Innodb的所有数据保存在一个单独的表空间里面,而这个表空间可以由很个文件组成,一个表可以跨个文件存在。6.所以其大小限制不再是文件大小的限制,而是其自身的限制7.-->in...
  • 关于mysql表数据大小我们知道mysql存储数据文件一般使用表空间存储当mysql使用innodb存储引擎的时候,mysql使用表存储数据分为共享表空间和独享表空间两种方式·共享表空间:Innodb的所有数据保存在一个单独的表空间...
  • ORACLE 表空间的转换

    2011-12-26 10:31:20
    由于前期的规划和人员的原因,有些表的表空间并没有统一,同一用户下出现多个表空间,这次数据库要升级,从ORACLE 9i 到 10g ,之前是导出一直出问题,后来发现是那台导出机器的问题,在其他的机器上用EXP导出都没有...
  • JavaEE学习日志持续更新----> 必看!JavaEE学习路线(文章总汇) ...2、实例:后台运行的一个进程,一个库可以有个实例,但一般只有一个实例。 3、表空间:逻辑存储单位,如cdef盘,就是逻辑分区
  • 、概述 system 表空间 字典所在 定义信息 system 一般不放用户数据 1.空间大小管理 .不要存为多个数据文件(可以设置自动扩展,或设置bigfile) ...
  • 关于MySQL 查询表数据大小的总结 一:关于mysql表数据大小 ...·共享表空间:Innodb的所有数据保存在一个单独的表空间里面,而这个表空间可以由很个文件组成,一个表可以跨个文件存在。 所以其大小...
  • ·共享表空间:Innodb的所有数据保存在一个单独的表空间里面,而这个表空间可以由很个文件组成,一个表可以跨个文件存在。 所以其大小限制不再是文件大小的限制,而是其自身的限制 -->innodb官...
  • ORACLE表分区以及信息查找...分区将表分离在若于不同的表空间上,用分而治之的方法来支撑元限膨胀的表,组表在物理级的可管理性.将表分割成较小的分区可以改善表的维护、备份分区概述为了简...
  • [20160721]rman与undo表空间备份.txt --//UNDO... --//一般生产数据库的UNDO表空间可能会变得非常巨大,甚至包括多个数据文件,而备份完整的UNDO数据文件在恢复时一般可能用到的比 --//例很小。所以UNDO的很大一部...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 922
精华内容 368
关键字:

一般一个表空间多大