MySQL的Schema设计

对于基于性能的数据库Schema设计,我们并不能完全以规范化范式理论来作为唯一的指导。在设计过程中,应该从实际需求出发,以性能提升为根本目标来展开设计工作,很多时候为了尽可能提高性能,我们必须做反范式设计。

一、高效的模型设计

1、适度冗余-让Query尽两减少Join
数据库的规范化理论其实质是在概念上的单一化,虽然规范后的数据库中的表一般都较小,使表中相关列最少。这虽然可能在某些情况下增强了数据库的可维护性,但在系统要完成一些数据的查询检索时,可能要用复杂的Join才能实现,这势必会造成查询检索的性能低下。如果我们通过拆分Join,通过多次简单的查询来在应用中实现Join逻辑,那所带来的网络开销将会是非常巨大的。

2、大字段垂直分拆-summary表优化
大字段垂直拆分策略相对于前面介绍的适度冗余策略在做法上可以说差不多是完全相反的做法。适度冗余策略是将别的表中的字段拿过来在自己身上也存一份数据,而大字段垂直拆分简单来说就是将自己身上的字段拆分出去放在另外(单独)的表里面。

继续阅读MySQL的Schema设计

MySQL的DISTINCT优化

三、DISTINCT的实现与优化
DISTINCT实际上和GROUP BY的操作非常相似,只不过是在GROUP BY之后的每组中只取出一条记录而已。所以,DISTINCT的实现和GROUP BY的实现也基本差不多,没有太大的区别。

同样可以通过松散索引扫描或者是紧凑索引扫描来实现,当然,在无法仅仅使用索引即能完成DISTINCT的时候,MySQL只能通过临时表来完成。

但是,和GROUP BY有一点差别的是,DISTINCT并不需要进行排序。也就是说,在仅仅只是DISTINCT操作的Query如果无法仅仅利用索引完成操作的时候,MySQL会利用临时表来做一次数据的“缓存”,但是不会对临时表中的数据进行filesort操作。

1、通过松散索引扫描完成DISTINCT
执行计划中的Extra信息为“Using index for group-by”,这代表什么意思?为什么我没有进行GROUP BY操作的时候,执行计划中会告诉我这里通过索引进行了GROUP BY呢?其实这就是于DISTINCT的实现原理相关的,在实现DISTINCT的过程中,同样也是需要分组的,然后再从每组数据中取出一条返回给客户端。而这里的Extra信息就告诉我们,MySQL利用松散索引扫描就完成了整个操作。

继续阅读MySQL的DISTINCT优化

MySQL的GROUP BY优化

二、GROUP BY的实现与优化
由于GROUP BY实际上也同样需要进行排序操作,而且与ORDER BY相比,GROUP BY主要只是多了排序之后的分组操作。当然,如果在分组的时候还使用了其他的一些聚合函数,那么还需要一些聚合函数的计算。所以,在GROUP BY的实现过程中,与ORDER BY一样也可以利用到索引。

在MySQL中,GROUP BY的实现同样有多种(三种)方式

1、使用松散(Loose)索引扫描实现GROUP BY
何谓松散索引扫描实现GROUP BY呢?实际上就是当MySQL完全利用索引扫描来实现GROUP BY的时候,并不需要扫描所有满足条件的索引键即可完成操作得出结果。

在执行计划的Extra信息中有信息显示“Using index for group-by”,实际上这就是告诉我们,MySQL Query Optimizer通过使用松散索引扫描来实现了我们所需要的GROUP BY操作。

要利用到松散索引扫描实现 GROUP BY,需要至少满足以下几个条件:
◆ GROUP BY条件字段必须在同一个索引中最前面的连续位置;
◆ 在使用GROUP BY的同时,只能使用MAX和MIN这两个聚合函数;
◆ 如果引用到了该索引中GROUP BY条件之外的字段条件的时候,必须以常量形式存在;

继续阅读MySQL的GROUP BY优化

MySQL的ORDER BY优化

除了常规的Join语句之外,还有一类Query语句也是使用比较频繁的,那就是ORDER BY,GROUP BY以及DISTINCT这三类查询。考虑到这三类查询都涉及到数据的排序等操作,所以我将他们放在了一起,下面就针对这三类Query语句做基本的分析。

一、ORDER BY的实现与优化

1、在MySQL中,ORDER BY的实现有如下两种类型:
◆ 一种是通过有序索引而直接取得有序的数据,这样不用进行任何排序操作即可得到满足客户端要求的有序数据返回给客户端;
◆ 另外一种则需要通过MySQL的排序算法将存储引擎中返回的数据进行排序然后再将排序后的数据返回给客户端。

2、第一种情况:
这种利用索引实现数据排序的方法是MySQL中实现结果集排序的最佳做法,可以完全避免因为排序计算所带来的资源消耗。所以,在我们优化Query语句中的ORDER BY的时候,尽可能利用已有的索引来避免实际的排序计算,可以很大幅度的提升ORDER BY操作的性能。

继续阅读MySQL的ORDER BY优化

MySQL Join的实现原理及优化思路

一、Join的实现原理

在MySQL中,只有一种Join算法,就是大名鼎鼎的Nested Loop Join,他没有其他很多数据库所提供的Hash Join,也没有Sort Merge Join。顾名思义,Nested Loop Join实际上就是通过驱动表的结果集作为循环基础数据,然后一条一条的通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果。如果还有第三个参与Join,则再通过前两个表的Join结果集作为循环基础数据,再一次通过循环查询条件到第三个表中查询数据,如此往复。

MySQL 8.0支持Hash Join了。

二、Join语句的优化

1、尽可能减少Join语句中的Nested Loop的循环总次数
如何减少Nested Loop的循环总次数?最有效的办法只有一个,那就是让驱动表的结果集尽可能的小,这也正是优化基本原则之一“永远用小结果集驱动大的结果集”。

2、优先优化Nested Loop的内层循环
不仅仅是在数据库的Join中应该做的,实际上在我们优化程序语言的时候也有类似的优化原则。内层循环是循环中执行次数最多的,每次循环节约很小的资源,在整个循环中就能节约很大的资源。

继续阅读MySQL Join的实现原理及优化思路

MySQL索引使用

一、索引的利处
很多朋友对数据库中的索引的认识可能主要还是只限于“能够提高数据检索的效率,降低数据库的IO成本”。

确实,在数据库中个表的某个字段创建索引,所带来的最大益处就是将该字段作为检索条件的时候可以极大的提高检索效率,加快检索时间,降低检索过程中所需要读取的数据量。但是索引所给我们带来的收益只是提高表数据的检索效率吗?当然不是,索引还有一个非常重要的用途,那就是降低数据的排序成本。

我们知道,每个索引中索引数据都是按照索引键键值进行排序后存放的,所以,当我们的Query语句中包含排序分组操作的时候,如果我们的排序字段和索引键字段刚好一致,MySQL Query Optimizer就会告诉mysqld在取得数据之后不用排序了,因为根据索引取得的数据已经是满足客户的排序要求。

那如果是分组操作呢?分组操作没办法直接利用索引完成。但是分组操作是需要先进行排序然后才分组的,所以当我们的Query语句中包含分组操作,而且分组字段也刚好和索引键字段一致,那么mysqld同样可以利用到索引已经排好序的这个特性而省略掉分组中的排序操作。

继续阅读MySQL索引使用

MySQL索引类型

在MySQL中,主要有四种类型的索引,分别为:B-Tree索引,Hash索引,Fulltext索引和R-Tree索引。

一、B-Tree索引

B-Tree索引是MySQL数据库中使用最为频繁的索引类型,除了Archive存储引擎之外的其他所有的存储引擎都支持B-Tree索引。不仅仅在MySQL中是如此,实际上在其他的很多数据库管理系统中B-Tree索引也同样是作为最主要的索引类型,这主要是因为B-Tree索引的存储结构在数据库的数据检索中有非常优异的表现。

一般来说,MySQL中的B-Tree索引的物理文件大多都是以Balance Tree的结构来存储的,也就是所有实际需要的数据都存放于Tree的Leaf Node,而且到任何一个Leaf Node的最短路径的长度都是完全相同的,所以我们大家都称之为B-Tree索引。当然,可能各种数据库(或MySQL的各种存储引擎)在存放自己的B-Tree索引的时候会对存储结构稍作改造。如Innodb存储引擎的B-Tree索引实际使用的存储结构实际上是B+Tree,也就是在B-Tree数据结构的基础上做了很小的改造,在每一个Leaf Node上面除了存放索引键的相关信息之外,还存储了指向与该Leaf Node相邻的后一个Leaf Node的指针信息,这主要是为了加快检索多个相邻Leaf Node的效率考虑。

继续阅读MySQL索引类型

MySQL Profiler使用

要想优化一条Query,我们就需要清楚的知道这条Query的性能瓶颈到底在哪里,是消耗的CPU计算太多,还是需要的的IO操作太多?

MySQL的Query Profiler是一个使用非常方便的Query诊断分析工具,通过该工具可以获取一条Query在整个执行过程中多种资源的消耗情况,如CPU,IO,IPC,SWAP等,以及发生的PAGE FAULTS,CONTEXT SWITCHE等等,同时还能得到该Query执行过程中MySQL所调用的各个函数在源文件中的位置。

1、打开profiling参数


mysql> set profiling=1;
Query OK, 0 rows affected, 1 warning (0.00 sec)

2、查询sql语句


mysql> select count(*) from t_crcs_check_diff;
+----------+
| count(*) |
+----------+
|    12608 |
+----------+
1 row in set (0.01 sec)

继续阅读MySQL Profiler使用

MySQL Explain使用

MySQL Query Optimizer通过我让们执行EXPLAIN命令来告诉我们他将使用一个什么样的执行计划来优化我们的Query。所以,可以说Explain是在优化Query时最直接有效的验证我们想法的工具。

在我们对某个Query优化过程中,需要不断的使用Explain来验证我们的各种调整是否有效。

一、我们先看一下在MySQL Explain功能中给我们展示的各种信息的解释:

1、ID:Query Optimizer所选定的执行计划中查询的序列号;

2、Select_type:所使用的查询类型,主要有以下这几种查询类型
1)DEPENDENT SUBQUERY:子查询中内层的第一个SELECT,依赖于外部查询的结果集;
2)DEPENDENT UNION:子查询中的UNION,且为UNION中从第二个SELECT开始的后面所有SELECT,同样依赖于外部查询的结果集;
3)PRIMARY:子查询中的最外层查询,注意并不是主键查询;
4)SIMPLE:除子查询或者UNION之外的其他查询;
5)SUBQUERY:子查询内层查询的第一个SELECT,结果不依赖于外部查询结果集;
6)UNCACHEABLE SUBQUERY:结果集无法缓存的子查询;
7)UNION:UNION语句中第二个SELECT开始的后面所有SELECT,第一个SELECT为PRIMARY;
8)UNION RESULT:UNION中的合并结果;

继续阅读MySQL Explain使用

oracle 19c学习(2)—导入10g数据库dmp文件

1、执行
CREATE USER c##posp IDENTIFIED BY posp;
ALTER USER c##posp QUOTA UNLIMITED ON USERS;
GRANT "CONNECT" TO c##posp;
GRANT "RESOURCE" TO c##posp;
GRANT CREATE ANY INDEX TO c##posp;
GRANT CREATE VIEW TO c##posp;
GRANT CREATE SESSION TO c##posp;
grant read,write on directory dmpdir to c##posp;

impdp c##posp/posp schemas=posp3 remap_schema=posp3:c##posp directory=dmpdir dumpfile=expdp_posp3.dmp logfile=impdp.log job_name=my_jod;

2、导入过程中提示错误
ORA-02374: conversion error loading table "C##POSP"."TBL_IPC_DFT_DSP"
ORA-12899: value too large for column IPC_DFT (actual: 266, maximum: 256)

ORA-02372: data for row: IPC_DFT : 0X'B9A4C9CCD2F8D0D0B3E5D5FDBDBBD2D7C7EBC7F32020202020'
因为字符集不一样
目标数据库字符集:al32utf8
源数据库字符集:zhs16gbk

没办法。。。

软件及互联网爱好者