来说说oracle的体系结构,这东西理论更多了……先给大家看个图片

——————————————————————————————————————————————————————

我们用的客户端就是User process比如我们的浏览器逛淘宝,之后买东西搜索的时候,就会产生一个PGA(用户全局区)会有几兆大小用来存放SQL,下一个黑乎乎的东西是我们的ecom数据库实例,这里有分为两部分,SGA和进程,这些进程我们之前用安装完查看过。SGA是在内存中划分的区域(系统全局区):共享池,数据库高速缓存池,重做日志缓存区,当然其实有六个部分,这里只介绍比较重要的三个,用户请求在实例中被接收之后,实例其实并不认识SQL语句,在shared pool的哈希计算把SQL语句翻译成Oracle能看懂的语句,之后我们的查询语句会在数据库高速缓存池中查询是否存在,如果不存在在向下查找磁盘,如果没有则返回没有,如果有数据则会将一份返回给用户,另一份存入缓存区;如果是插入SQL同样也会先写到高速缓存区,之后通过进程将缓存写入到磁盘中永久保存。当然这些操作都会被记录在日志中也就是重做日志缓存区,以防止突然出错,当满足一定条件后会由进程写入到磁盘中保存,当库恢复会自动先读取日志。下面蓝色的就是磁盘区域,里面的三个:数据文件,控制文件,日志文件在不被损坏的情况下,理论上可以恢复数据库。左面的是pfile和spfile文件。

来看看SQL的执行过程:

sql 执行过程
1、检查语法(检查语法,如果有错误,直接返回,省着往下执行浪费资源)  seclt *  form nimei;
2、检查语义(有没有这个表、当前用户有没有操作权限,如果没有直接返回)
3、hash计算(把当前的sql语句转换成oracle可以理解的hash值)
4、解析
    4.1软解析(当一条sq1语句执行过,就会保存在library cache中,当再一次执行与此条sql相同的语句时,不经过cpu计算,直接调用share pool)

select * from test====>编译成一个XXXX的指令集
    select * from test
    4.2硬解析(当软解析不成功进,经过cpu计算)
5、执行

select name from test where id=1(先计算条件,再对比表,减少查找范围,触发索引就是先看where)

不知道大家发没发现,软解析是在缓存中执行的而硬解析需要计算,那么如果我们的SQL全部被软解析是不是会大幅提升性能呢?那么来看看如何提高SQL在share pool中的命中率:

生产中share pool的命中率,应达到90%以上,这样cpu的压力就小了
    触发条件:
     1、标准化,书写规范
            SELECT name FROM emp WHERE id=1; 
            select NAME from EMP where ID=1; 
            举例:一个大项目,肯定由多个人来完成,所以一条SQL可能会被调用很多次,这时share pool就会有缓存。
            
     2、使用绑定变量
        select 价格 from emp where name=1;
        select 价格 from emp where name=2;        
      举例:互联网中,使用人比较多,每个人执行的操作不同,SQL条件也不同。
        select 价格 from emp where name=:a;【绑定变量,执行SQL前给绑定变量name先赋值=1,然后再执行】
        select 价格 from emp where name=:a;【绑定变量,执行SQL前给绑定变量name先赋值=2,然后再执行】

当我们执行SQL的时候会调用很多数据字典,因为这些数据字典会被重复使用,所以有了一个data dictionary cache缓存区

Oracle中有一个CBO优化器:衡量SQL执行计划的,选择一种最优的执行方式。他会选择一种最快的执行方式,一般都是索引。

假设:emp表有10W行
  收集器收集后,全表扫描emp表的cost的开销1000
  收集器收集后,索引rowid扫描emp表的cost的开销10      这样就会选择后面的一种

一般Oracle数据库都是在晚上空闲的时候运行收集器,去收集开销。

10g以前的,优化器是RBO,基于规则的(认为索引扫描就是比全表扫描快)
有1个表是10行,存放在1个表数据块上。
   如果先查索引块开销1,再查询表数据块开销1,一共开销2。
   如果直接查询表数据块开销1,一共开销1。

10g开始是CBO,基于规则的cost。
假设a表晚上只有10行,收集器收集了,早上的时候a表中insert了10W行,收集器不会收集。但是表产生的变化会写到数据字典中,如果当前一个对象,它的变化超出阀值(不管阀值是多少,Oracle自己定的)触发收集。

假设a表有100W行,第2天我Insert一条,再delete一条,对于cpu计算的结果没有影响。

假设a表有100W行,第2天我Insert了50W,它的变化超出阀值,就会告诉收集器收集一下。

redo log buffer cache:先写内存中,速度快,它认为内存中写完,此次操作就完了,当库空闲的时候再把内存的数据写到磁盘的redo日志文件中,主流数据库,都是先写日志,再写数据库。日志比较重要,日志健全,数据没了,可以通过日志进行恢复。

large pool  存储大操作的数据【一次提取大的数据,存储在大池比较好,存储database Buffer cache就不好了,容易造成命中假像】large pool存放:1、RMAN的备份数据 2、并行操作

java pool   调用前端的java指令

这5个池全在SGA(系统全局区域),在内存中分配了SGA区,在SGA又配合了以上5个池,这些池是为了加快访问速度。

share_pool:用于缓存SQL语句以及SQL语句中涉及的表定义(数据列以及数据类型)

——————————————————————————————————————————————————————

当执行一个sql语句,就会被记录,在生产平台上,很多sql语句会被很多人重复执行,所以,缓存了的sql语句,会被更快的执行。

——————————————————————————————————————————————————————

——————————————————————————————————————————————————————

——————————————————————————————————————————————————————

——————————————————————————————————————————————————————

下面其他的缓存也提供了测试方法

Database buffer cache(作用:缓存数据)
Buffer cache存储从数据文件检索出来的数据块拷贝,提升数据检索速度,降低IO压力

SQL> create table aa as select * from dba_objects;

SQL> alter system flush shared_pool;
SQL> alter system flush buffer_cache;

打开自动跟踪
SQL> set autotrace traceonly;     【关闭  set autotrace off;】

SQL>select count(*) from aa;
结果:
 5184  consistent gets (逻辑读 内存)
 914  physical reads   (物理读 硬盘)

再次执行
SQL> set autotrace traceonly;
SQL>select count(*) from aa;
结果:
       5047  consistent gets(只有逻辑读 说明都是从内存读出的)
          0  physical reads
-----------------------------
查看共享池
SQL> select pool,sum(bytes/1024/1024)from v$sgastat t where t.POOL is not null group by t.POOL;
SQL> show parameter shared_pool_size;

SQL> alter system set shared_pool_size=64m scope=both;(scope=spfile此参数可以直接修改到内存和参数文件不需要重启)

SQL> select pool,sum(bytes/1024/1024)from v$sgastat t where t.POOL is not null group by t.POOL;
SQL> show parameter shared_pool_size;

你会发现share pool有2个不同值

SQL> shutdown immediate;
SQL> startup
SQL> select pool,sum(bytes/1024/1024)from v$sgastat t where t.POOL is not null group by t.POOL;
SQL> show parameter shared_pool_size;
重启后,依然不会变化,share pool有2个不同值,所以咱们不用修改,10g以后是段自动管理,除非你把段自动管理关闭,它才会生效。

SQL> select pool,sum(bytes/1024/1024)from v$sgastat t where t.POOL is not null group by t.POOL;【以这个查询出的share pool为准】

不管share pool、buffer cache全是在SGA中划分出来的,share pool、buffer cache受SGA管理,你开启自动管理功能不用手工设置,受SGA控制。
SGA变大,share pool、buffer cache也会变大。SGA变小,share pool、buffer cache也会变小。

显示SGA的所有设置值
SQL> select pool,sum(bytes/1024/1024)from v$sgastat t where t.POOL is not null group by t.POOL
    union
    select name as pool,sum(bytes/1024/1024) from v$sgastat s where s.POOL is null group by s.name;

SQL> show parameter sga;

SGA是动态的并且最大值由SGA_MAX_SIZE参数控制【sga中划分的所有池,它们相加总和不可以超过sga_target。如果想把SGA中划分的各个池调大,由于SGA自动管理,SGA变大,这些划分的各个池也会变大】

SQL> show parameter sga

SGA大小受2个参数影响:sga_target、sga_max_size

sga_max_size相当于你钱包里有多少钱,sga_target你要买的东西的价格
你钱包里有1000元,你买双500元的鞋。你钱包里有1000元,你买1500元的鞋,买不了吧!

在oracle运行过程当中修改SGA_TARGET值不能大于SGA_MAX_SIZE,生产中sga_target和sga_max_size大小致最好,就不会出问题了。
就是你有1000元钱,你买双1000元的鞋,正好~!

如果SGA_MAX_SIZE配置值小于SGA_TARGET,那么在数据库启动后SGA_MAX_SIZE= SGA_TARGET,在此期间SGA_TARGET不能向上调整
你谈个女朋友,你钱包里有1000元,人家要1500元的包,你是不是也得买啊?哪怕你是借钱

SQL>select pool,sum(bytes/1024/1024)from v$sgastat t where t.POOL is not null group by t.POOL
    union
    select name as pool,sum(bytes/1024/1024) from v$sgastat s where s.POOL is null group by s.name;
SQL> show parameter sga
SQL> alter system set sga_max_size=350M scope=spfile;
SQL> shutdown immediate;
SQL> startup
SQL> show parameter sga 【如果SGA_MAX_SIZE配置值大于SGA_TARGET,那么在数据库启动后SGA_MAX_SIZE, SGA_TARGET分别使用自己的配置值】
SQL> select pool,sum(bytes/1024/1024)from v$sgastat t where t.POOL is not null group by t.POOL
    union
    select name as pool,sum(bytes/1024/1024) from v$sgastat s where s.POOL is null group by s.name;
    
  各个池没有变化,它们受sga_target影响,不受sga_max_size,上面咱们修改的是sga_max_size大小,所以各个池没有变化 
    
    
SQL> alter system set sga_target=400M  scope=spfile;
SQL> shutdown immediate;
SQL> startup
SQL> show parameter sga 【sga_max_size和sga_target一样了,sga_max_size迁就sga_target】    
SQL> select pool,sum(bytes/1024/1024)from v$sgastat t where t.POOL is not null group by t.POOL
    union
    select name as pool,sum(bytes/1024/1024) from v$sgastat s where s.POOL is null group by s.name;

buffer cache和share pool有变化

生产中最简单的调优方式,扩大内存吧,所以服务器内存没有小于16G。

在oracle 10g后,SGA下的各个小池大小不需要咱们手工修改,你只需要会修改SGA,就可以了。

scope=spfile【修改参数文件,当前没有生效,要重启】
scope=both;【1修改到参数文件、2修改到内存当前生效,不需要重启】

memory_max_size
memory_target

接下来再来看看Oracle存储结构:

——————————————————————————————————————————————————————

逻辑结构
 库 database、tablespace表空间、segments段、     extents区扩展、   blocks块
【某居民小区、某居民小区一期、 一期小区内一栋楼、楼内的某一单元、  某单元内的某一室】

段名和表名一样,一个普通表占用一个段(分区表不是这样的),小表的段内区少,大表的段内区多

新建一个空表,占用64K(表内有1个段,1个段内有1个区,1个区内有8个块,每个块默认8K)

create table nimei as select * from dba_objects where 1=2;

查看分区、块信息
select BYTES/1024,BLOCKS,EXTENTS from user_segments where segment_name='空表名'
BYTES/1024        BLOCKS    EXTENTS
--------------- ---------- ----------
           64        8          1

select BYTES/1024,BLOCKS,EXTENTS from user_segments where segment_name='NIMEI';

create table ttt as select * from dba_objects;

select bytes/1024/1024 from user_segments where segment_name='TTT';查看表有多大(M)

查看当前用户中最大的表
select SEGMENT_NAME,BYTES/1024/1024,BLOCKS from user_segments where bytes =(
    select max(bytes)from user_segments
);

select b.SEGMENT_NAME, b.BYTES / 1024 / 1024, b.BLOCKS
  from (select a.SEGMENT_NAME, a.BYTES, a.BLOCKS, rownum rn
          from (select SEGMENT_NAME, BYTES, BLOCKS
                  from user_segments
                 order by BYTES desc) a) b
 where b.rn = 1

查看分区、块分配具体信息

select * from user_extents where segment_name='TTT'

【区的智能化管理】
段中区越多,寻址不方便,存储的数据量达到一定程度,区中的块的个数会扩大,减少区的数量,方便管理。

去超市买东西,超市的方便袋分为:大、中、小
你买2瓶水,买个小袋就可以了。
你买10瓶水和一些小吃,买个中袋就可以了。
你买了一些日常用品、蔬菜和水果、20瓶饮料,买个大袋就可以了。

delete from ttt;
查看分区、块分配具体信息
select * from user_extents where segment_name='TTT'; 【区没有减少】

insert into ttt select * from dba_objects;
查看分区、块分配具体信息
select * from user_extents where segment_name='TTT'; 【区没有增加】

虽然数据没了,如果我把区收缩没了,我的删除效率会慢,我要再插入数据时,我再重新建立。
如果不回收,我删除快了,我写入快了。但是影响查询速度。

create table hehe as select * from all_objects;
delete from hehe;
commit;
insert into hehe  select * from all_objects;
commit;
delete from hehe;
commit;
insert into hehe  select * from all_objects;
commit;
delete from hehe;
commit;
insert into hehe  select * from all_objects where rownum<3;
commit;

set autotrace traceonly;
select * from hehe where object_id=20;【 741  consistent gets 逻辑读大些】

create table haha as select * from all_objects where 1=2;
insert into haha  select * from all_objects where rownum<3;
commit;
set autotrace traceonly;
select * from haha where object_id=20;【 8  consistent gets 逻辑读小些】

select * from user_extents where segment_name='HEHE';
select * from user_extents where segment_name='HAHA';

hehe表占21个区,haha表占1个区,是咱们生产中常见问题,表碎片。
一个表反复增删改,它就会产生碎片。
碎片就是我的数据不连续【有图】
碎片越多,剩余空间越多,浪费空间。对于查询来说,范围越大,查询越慢。 
 
hehe表和haha存储的数据一模一样的,但是查询成本不同。
hehe表是从21个区中找 object_id=20的记录,haha表是从1个区中找 object_id=20的记录,

alter table 表 move 【tablespace 表空间】--------表收缩(把表内容重新写一下,让表所在的空间减少,索引会失效了)

在生产环境中,怎么去判断?不用总去做,一个月或几个月做一次,一定要在业务不忙时做。
这就是工作经验了,你在公司维护数据库,经常访问的几个主要表,你一定知道。这几个表多做监控,比如说:

你判断2个值

1、表记录的行数   5W----->6M大小(假设正常情况) 
2、表对应的大小   10W---->30M大小(不成正比,肯定不正常了,这里面肯定有碎片了)

所以你经常做增删改操作,会产生大量碎片,有碎片就要移动,就是把里面的数据重新写一下。
表小移动一下,非常快。如果表中有几百W行,移动一下会非常慢,所以表的移动不能天天弄,可以按月来操作。

举例:
有些兄弟上班后,知道表移动可以加快查询速度。移动后就完蛋了,你的CPU压力变大了,你的I/O压力也变大了,这是为什么呢?
在公司维护一定要记录,移动表索引失效了。
索引的查询方式。索引和表有一个对应关系,通过rowid。

SQL> create table ff as select * from dba_objects;
SQL> set autotrace traceonly;
SQL> select * from ff where object_id=20;【全表扫描】
SQL> create index I_FF on ff (object_id);
SQL> select * from ff where object_id=20;【可以命中索引】
SQL> alter table ff move;
SQL> select * from ff where object_id=20;【全表扫描】
SQL> select status from user_indexes where index_name = 'I_FF';

UNUSABLE 失效
VALID    正常
N/A      分区索引

SQL> alter index I_FF rebuild;(类似操作:先把索引删除+再新建)

你把表移动完了,表的碎片没了,你把索引也弄失效了,你的主要表查询全表扫描,什么样的服务器也抗不住啊。
move之前应把索引offline或off或删除 【move后rebuild】

【表碎片处理的4种方法】

1、数据导出导入(imp/exp    impdp/expdp)
2、alter move【索引会失效,移动完成的瞬间会阻塞操作】
3、truncate
4、create table 新表 as select * from 旧表;【把旧表、新表的名称互换一下】

当前ttt有碎片

create table ttt as select * from dba_objects;
create index I_TTT on ttt (object_id);

create table fff as select * from ttt;  【新表fff中没有ttt表上的索引,索引无法克隆,别忘了把索引加上】

select TABLE_NAME,INDEX_NAME,status from user_indexes where TABLE_NAME in('TTT','FFF');

rename  ttt to vfast;
rename fff to ttt;

create table test as select * from dba_objects;
delete from test;
select count(*) from test;
rollback;【从undo取回来】
select count(*) from test;【数据回来了,之前删除的数据被放在undo中了】

create table test2 as select * from dba_objects;
create table test3 as select * from test2;

set timing on

delete from test2;           【操作慢】
rollback; 
select count(*) from test2; 【恢复了数据】

truncate table test3;        【操作快】
rollback;
select count(*) from test3;【没有恢复数据】

总结:
delete
   逐行删除、删除慢、
   产生大量日志(块变化就会产生日志,delete会操作很多块)、
   产生大量的undo数据,可以回滚、删除后可以恢复
   太费I/O、
   
占3份I/O,你删除之前先记录日志,往日志里写,占1份I/O。你表删除操作的I/O、同时undo写的I/O
如果删除1000W记录,删除到500W行时,Undo没有空间了,要保持一致性,回滚到删除之前的状态,表还是1000W行,又费了一份I/O,往表中回写的I/O。
所以大表的清空删除,使用delete直接操作,容易把库干瘫痪了,太费I/O了。
   
   可以加where条件

truncate
   删除快、
   产生少量的日志(删除动作会产生日志,删除后会把区收缩了,产生数据很小),
   不产生undo数据、
   不可加where
   
   
   
create table test4 as select * from dba_objects;
create table test5 as select * from test4;
select count(*) from user_extents where segment_name='TEST4';【test4有多少区?21个区】
select count(*) from user_extents where segment_name='TEST5';【test5有多少区?21个区】

delete from test4;
commit;
select count(*) from test4;

truncate table test5;
select count(*) from test5;
   
   select count(*) from user_extents where segment_name='TEST4';【还是21个区】
   select count(*) from user_extents where segment_name='TEST5';【1个区,区被回收了】

生产中清空大表基本用的是truncate,操作起来比较快。但是无法rollback恢复,具有危险性。

删除大表中的部分数据,只能用delete,可以分批删除。【   delete 配合 where 配合rownum】
1000W的表,每10W删除一次,把大的动作变小。

------------------------------------------

操作os(系统块) ext3 为4k
oracle 块为系统块的整数倍 默认8k

oracle中我们可以设置不同的大小  2,4,8,16,32(32位操作系统不支持32k的块)

mysql 默认块16k  db2 默认块4k

什么时候要改变块大小?对你的操作有什么影响?

对读写效率有影响。

最小块是8K,select * from table where id=1,这条记录可能占10个字节,但是你访问最小范围是1个块,8K可以看成最小存储单元。

你块越小,你寻址时,查询起来越费劲。

举例:
1000W记录的表,块默认是8K大小的,假如占10000个块,你要读1条记录,这条记录可能占10个字节,你访问的范围是1个块,从10000个块中找1个块。
1000W记录的表,块默认是16K大小的,假如占5000个块,你要读1条记录,这条记录可能占10个字节,你访问的范围是1个块,从5000个块中找1个块。

所以针对读动作来说,
1、寻址:块越大越好
2、扫描:块越小越好

OLTP业务:读写比较频繁,你寻址和扫描都多,块大小默认设置成8K就行。
OLAP分析业务:提取数据量大、没有OLTP操作频繁,设置成16K、32K,分析为主。

举例:
我分析一下,全年交易,可能扫10个表,每个表扫描几百W行,所以说OLAP业务做成大块好一些。

9i 开始 允许不同的表空间使用 不同的块大小

SQL> create tablespace testnblock
 datafile '/oracle/app/oradata/ecom/testnblock.dbf' size 10M
 blocksize 16k;
create tablespace testnblock
*
ERROR at line 1:
ORA-29339: tablespace block size 16384 does not match configured block sizes

SQL> show parameter db_16k_cache_size;【sga中没有16k的存放空间,默认为0】

SQL> alter system set db_16k_cache_size = 10M;【没有加scope,就等于scope=both,sga为16K块分配10M空间】

System altered.

SQL> create tablespace testnblock
 datafile '/oracle/app/oradata/ecom/testnblock.dbf' size 10M
  blocksize 16k;

create table af tablespace testnblock as select * from dba_objects;
create table aff as select * from af;

select count(*) from user_extents where segment_name='AF'; 【20个区】
select count(*) from user_extents where segment_name='AFF';【21个区】

AF使用的表空间是16K的,AFF使用的表空间是默认8K的,可以看出AF区内的块数明显比AFF区内的块数少,所以寻址定位更快了。

如果设计库,有多少表,表之间的关联是什么样的?我在一个块内一般存放多少行数据比较好一些?

比如:
8k=8*1024=8192字节

一个块8K,一个块中保留10行记录,一行记录最多800字节。我们觉得一行800字节挺少,在生产中正常。

SQL> create table ab as select * from dba_objects;

SQL> analyze table ab compute statistics;(分析表,分析结果存放在动态性能视图库中,我们可以去查询)

SQL> select avg_row_len from user_tables where table_name='AB';
(查看平均行长度(一行大约占多少字节),单位字节,一个块 至少能存储一行)

然后用块的默认大小/平均行长 = 一个块内存多少行

8192/97=84.4536082 ~=84行

通过上面实验,能推断一行占多少空间,理论上一个块能装84行。

——————————————————————————————————————————————————————

下一篇将会介绍Oracle的控制文件和日志文件。

大数据培训之旅——Oracle-6(体系结构)相关推荐

  1. 大数据培训之旅——Oracle-8(存储过程,权限)

    存储过程这东西还是相当关键的,说白了就是一堆 SQL 的合并,当然中间需要套用逻辑业务,类似于Java中的程序. [优点]   1.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而 ...

  2. 大数据培训之旅——Java-9(设计模式、Java Web)

    java终于要完事了,最后一篇Java的文章,设计模式和Java Web,当然因为我们不是纯Java开发,所以这俩了解了解就可以了.这篇应该是文字最多的了.Java之后应该就是Oracle数据库了.如 ...

  3. 大数据培训之旅——Oracle-2(基础操作,数据字典,基础SQL)

    我们在上一篇里把Oracle10g安装好了,那么也算是有工具了,下面就得看看如何使用了. ------------------------------------------------------ ...

  4. 2018大数据培训学习路线图(详细完整版)

    2018大数据培训学习路线全课程目录+学习线路详解(详细完整版) 第一阶段:大数据基础Java语言基础阶段 1.1:Java开发介绍 1.1.1 Java的发展历史 1.1.2 Java的应用领域 1 ...

  5. 大数据课程培训大纲详解,大数据培训学习内容

    大数据助力成就非凡.大数据正在改变着商业游戏规则,为企业解决传统业务问题带来变革的机遇.毫无疑问,当未来企业尝试分析现有海量信息以推动业务价值增值时,必定会采用大数据技术.那么大数据培训哪家好呢?今天 ...

  6. 大数据培训:Hadoop HDFS 实现原理

    一.HDFS体系结构 1.1 HDFS 简介 Hadoop分布式文件系统 (HDFS) 是运行在通用硬件(commodity hardware)上的分布式文件系统(Distributed File S ...

  7. 深圳大数据培训:HDFS基本概念

    深圳大数据培训:HDFS基本概念 1.1 HDFS的介绍 源自于Google的GFS论文 发表于2003年10月 HDFS是GFS克隆版 ,HDFS的全称是Hadoop Distributed Fil ...

  8. 大数据培训 | 数据仓库构建方法论和实践

    数据仓库的价值 构思一个主题讨论数据仓库的构建方法论,包括数据仓库的价值.选型.构建思路,随着数据规模膨胀和业务复杂度的提升,大型企业需要构建企业级的数据仓库(数据湖)来快速支撑业务的数据化需求,与传 ...

  9. 大数据培训Hive的数据存储与压缩

    行存储与列存储 当今的数据处理大致可分为两大类,联机事务处理 OLTP(on-line transaction processing)联机分析处理 OLAP(On-Line Analytical Pr ...

最新文章

  1. simple_html_dom meta,HTML DOM Meta content 属性
  2. python如何询问_学习Python问?
  3. rsync同步和备份文件到本地
  4. 周报 2016.04.10
  5. oracle sqlcode 多条,SQL查询以连接Oracle中多个行的列值
  6. Javascript学习总结 - JS基础系列 二
  7. 金融情报挖掘:面向公开文本的期货事件聚合与传导因素分析
  8. 信息学奥赛一本通 1130:找第一个只出现一次的字符 | OpenJudge NOI 1.7 02
  9. php v9 邮箱登陆,PHPCMS v9会员登录支持Email登录的实现方法
  10. Atitit gui的实现模式文本 dom ast 像素绘图api native 目录 1. Pl ast xml domAst 1 1.1. 简介 1 1.1.1. 【具体语法树】 2 2.
  11. oracle数据库中标识列,Oracle数据库标识列
  12. OpenCV4机器学习(一):OpenCV4+VS2017环境搭建与配置
  13. 宕机怎么读?服务器宕机是什么意思?
  14. python量化交易--因子选股策略
  15. DVWA的搭建以及文件上传漏洞各个等级测试
  16. GTD软件比较和选用
  17. 大数据——何谓“大”
  18. Python使用Plot库构图--详细教程
  19. AD2019 层次原理图
  20. 网络编辑招聘笔试题(答案)

热门文章

  1. android图片收藏,收藏 Android-PickerView
  2. [附源码]Python计算机毕业设计SSM化妆品网上商城数据分析系统(程序+LW)
  3. python: isspace函数
  4. 淘宝卖家订单速记表selenium +requests爬取 openpyxl +xlrd 操作excel
  5. unity 自动寻路爬楼梯效果
  6. AJAX入门——不加载整个页面,与服务器交换数据并更新部分网页内容
  7. Scrapy--模拟登录
  8. 英雄体育VSPN冲刺港股:9个月营收超13亿 腾讯是股东
  9. Unity项目进阶之保卫萝卜一.UI搭建
  10. 三种方式将wmv格式的视频快速转为mp4