`
kiddwyl
  • 浏览: 402663 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

CBO学习笔记

阅读更多
cost of b-tree access

这一节我们看看CBO是如何来计算最普通的b-tree索引的访问的cost的。

我们知道B-tree索引的结构是一个树状结构,索引中包括root block,branch block, leaf block,这些结构分别相当与树的根,茎和叶。
当我们使用一个索引的时候,我们首先访问索引的root block,确定需要访问大branch block。
然后选择需要访问的branch blcok,通过访问branch block,我们知道符合我们条件的第一个leaf block,可以叫做start key
我们从start key访问leaf block的列表,知道找到我们需要的最后一个leaf block--->stop key。
访问符合条件的leaf block的时候,并视情况而定要不要访问相应的表。我们知道leaf block上的信息包括被索引的列的值和在表中相应行的rowid,所以如果我们只需要查询被索引的列上的信息,我们就无需访问index对应的表,否则就需要访问表。

我们知道CBO的Cost包括IO的cost和CPU的cost,而Oracle认为每一个single block access都是一个真实的IO,所以如果我们启动CPU的cost,访问索引的Cost就是访问索引的Block个数。

访问索引的cost可以用下面的公式来表示:

cost = blevel +
ceiling(leaf_blocks * effective index selectivity) +
ceiling(clustering_factor * effective table selectivity)

第一行的blevel是指为了访问一个leaf block,我们需要访问的block的个数(不包括leaf block本身),Oracle总是维护一个Balanced B-trees,也就是说不管访问哪桓鰈eaf block,我们需要访问的中间block(包括root block和branch block)的个数都是一样多的。这个blevel也常常被称为索引的高度。

第二行是指我们的查询需要访问的leaf block的个数。

第三行是指为了获取我们需要的所有数据,我们需要访问的表的block的个数。

我们来做个实验来验证上面的公式。

1) 建表,建索引并收集统计数据:
create table t1
nologging
as
select
trunc(dbms_random.value(0,25)) n1,
rpad('x',40) ind_pad,
trunc(dbms_random.value(0,20)) n2,
lpad(rownum,10,'0') small_vc,
rpad('x',200) padding
from
all_objects
where
rownum <= 10000
;

create index t1_i1 on t1(n1, ind_pad, n2)
nologging
pctfree 91
;

begin
dbms_stats.gather_table_stats(
user,
't1',
cascade => true,
estimate_percent => null,
method_opt => 'for all columns size 1'
);
end;
/

我们查询表和索引的统计信息:
select
table_name,
blocks,
num_rows
from user_tables
where table_name = 'T1'
;

TABLE_NAME BLOCKS NUM_ROWS
------------------------------ ---------- ----------
T1 371 10000

(HWM下有371个block,一共有10000行)

select
num_rows, distinct_keys,
blevel, leaf_blocks, clustering_factor,
avg_leaf_blocks_per_key, avg_data_blocks_per_key
from
user_indexes
where table_name = 'T1'
and index_name = 'T1_I1'
;

NUM_ROWS DISTINCT_KEYS BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR AVG_LEAF_BLOCKS_PER_KEY AVG_DATA_BLOCKS_PER_KEY
---------- ------------- ---------- ----------- ----------------- ----------------------- -----------------------
10000 500 2 1112 9745 2 19

(索引上一共有10000行,
索引的列上的distinct key是500个,
这个索引的blevel=2,也就是说有一个level 2的root block和多个level 1的branch block,
一共有1112个leaf block,
cluster_factor=9745,
平均的说,索引上每一个distinct key占用2个索引leaf block,
平均的说,索引上每一个distinct key占用19个table block。

这里简单解释一下几个概念:
1,distinct key,
因为我们被索引的列是n1, ind_pad,n2。其中n1有25个不同的值,ind_pad的值总是一样的,n2有20个不同的值,所以索引上distinct key=25*1*20=500。

2,cluster_factor,
这是一个判断表上的数据分布是不是和索引一样有序的一个值,它的取值范围在表的block的个数和表的行数之间,越接近block的个数说明表的数据分布越有序(和索引一样有序),越是接近行数越说明表上的数据分布是混乱的。
可以这样理解cluster_factor,当我们按照索引上的顺序访问表的时候,每当我们需要的数据不在当前block上的时候,我们就要“跳到”其他block上进行访问,如果表上的数据排列和索引是完全一样的话,我们跳的次数等于表的Block的个数,如果是另一个极端,表的数据分布极其的混乱,我们访问每一行数据都要跳一次,那我们最后跳的次数就等于行数。这里跳的次数就是cluster_factor。从这个角度来说,如果我们访问索引之后还有相应的访问表,假设我们访问了X%的索引block,那我们需要访问表的IO次数应该是X% * cluster_factor,取决于X和cluster_factor的大小,X% * cluster_factor有可能比表的所有block的个数还有多(当然这种情况下很有可能CBO已经选择全表扫描了),因此cluster_factor对于计算索引访问的Cost是很重要的,经常可以用来回答类似与“为什么我们索引没有被使用这类问题”。

下面是一个cluster_factor=10的图示:


需要明确的是根据公式
cost = blevel +
ceiling(leaf_blocks * effective index selectivity) +
ceiling(clustering_factor * effective table selectivity)
的第三个部分我们知道cluster_factor越小访问索引COST的就越小(当然是在访问完索引后不得不也访问表的情况下),但cluster_factor大小其实不是衡量索引好坏的标准,这个值是因为表本身的数据分布和索引排列数据顺序不符所造成的,即使我们rebuild索引,cluster_factor也不会改变(只要索引的定义没有改变)。

实验1

 

先做个简单的实验:
select
small_vc
from
t1
where
n1 = 2
and ind_pad = rpad('x',40)
and n2 = 3
;

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=25 Card=20 Bytes=1160)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T1' (Cost=25 Card=20 Bytes=1160)
2 1 INDEX (RANGE SCAN) OF 'T1_I1' (NON-UNIQUE) (Cost=5 Card=20)

我们看到索引本身RANGE SCAN的Cost=5,Card=20, 最后的总cost是25,也就是table的访问cost是20,按照我们个公式:

cost = blevel +
ceiling(leaf_blocks * effective index selectivity) +
ceiling(clustering_factor * effective table selectivity)
我们算一下:
blevel =2
leaf_blocks=1112
effective index selectivity = (selectivity of n1)*(selectivity of ind_pad)*(selectivity of n2)= (1/25)*1*(1/20)=1/500=0.002
clustering_factor=9745
effective table selectivity在这里其实是和索引的effective index selectivity一样的=(selectivity of n1)*(selectivity of ind_pad)*(selectivity of n2)= (1/25)*1*(1/20)=1/500=0.002

放在一起我们得到
cost = 2+ ceil(1112*0.002) + ceil(9745*0.002)=2+ 3 + 20 = 25。
其中2+3是索引访问本身的cost,20是表的访问cost。

从这个例子里我们发现表本身的cost占绝大多数,这是因为这个索引的clustering_factor很大。很多时候我们都希望重建索引可以大大提高提高索引的效率,但要记住重建索引只能减少leaf_blocks的值(能减少多少取决于索引的具体情况),但实际上有时候真正影响更大的是clustering_factor(当然有时候是leaf_blocks,取决于具体情况)。

实验2

 

我们在条件里面加一个范围查询:

select
/*+ index(t1) */
small_vc
from
t1
where
n1 = 2
and ind_pad = rpad('x',40)
and n2 between 1 and 3
;

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=93 Card=82 Bytes=4756)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T1' (Cost=93 Card=82 Bytes=4756)
2 1 INDEX (RANGE SCAN) OF 'T1_I1' (NON-UNIQUE) (Cost=12 Card=82)

首先我们加了一个/*+ index(t1) */强制使用索引,否则这个查询会选择full table scan,因为如果你实验一下或按照我们以前介绍的方法算一下,这个表的full table scan的cost只有58。
我们再算一下cost:

selectivity (n2 between 1 and 3) =
required range / total range + 1/num_distinct + 1/num_distinct =
(3 – 1) / (19 – 0) + 1/20 + 1/20 = 0.205263

Effective index selectivity = 1 * 0.04 * 0.205263 = 0.0082105
Effective table selectivity = 1 * 0.04 * 0.205263 = 0.0082105
Cost = 2 + ceiling(1,112 * 0.0082105) + ceiling(9,745 * 0.00082105) = 12 (index的扫描cost) + 81(table的扫描cost) = 93

实验3

 

我们修改一下上面的SQL:

alter session set "_optimizer_skip_scan_enabled"=false;
select
/*+ index(t1) */
small_vc
from
t1
where
n1 between 1 and 3
and ind_pad = rpad('x',40)
and n2 = 2
;

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=264 Card=82 Bytes=4756)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T1' (Cost=264 Card=82 Bytes=4756)
2 1 INDEX (RANGE SCAN) OF 'T1_I1' (NON-UNIQUE) (Cost=184 Card=1633)

我们这里修改_optimizer_skip_scan_enabled为false,这样CBO就会使用Cost更低的Index skip scan。

这次我们发现总的cost相当高,但是按照公式计算:
selectivity (n1 between 1 and 3) =
required range / total range + 1/num_distinct + 1/num_distinct =
(3 – 1) / (24 – 0) + 1/25 + 1/25 = 0.163333

Effective index selectivity= 0.163333*1*0.05=0.0081667
Effective table selectivity = 0.163333*1*0.05=0.0081667
cost= 2 +
ceil(0.0081667 * 1,112)
ceil(0.0081667 * 9745)
= 92

我们的公式结果和explain plan里的显示差很多,这是为什么呢?
原因在于复合索引存储的方式,因为复合索引存储数据的时候首先是按照第一个被索引的列来排序的,也就是说把n1=0的放在,然后是n1=1的放在一起,然后n1=2......
类似于(这里只是大概描述一下概念,不一定准确):
第一组:
n1=0
{ind_pad='x ' (n2=0, n2=1,n2=2....n2=19)}

第二组:
n1=1
{ind_pad='x ' (n2=0, n2=1,n2=2....n2=19)}

.....

第二十五组:
n1=24
{ind_pad='x ' (n2=0, n2=1,n2=2....n2=19)}


所以当我们第一个条件是n1 between 1 and 3的时候,如果没有开启从oracle9i里面开始引进的index skip scan,其实CBO是很郁闷的,因为他要扫描很多block才能获得n1 between 1 and 3的结果,实际上在这种情况下,CBO忽略了后面的ind_pad和n2的查询条件,而是查询了所有n1 between 1 and 3的leaf block再从中选出符合ind_pad和n2的查询条件的leaf block,所以这里
Effective index selectivity = index selectivity of n1 = 0.163333,但是Effective table selectivity还是= 0.163333*1*0.05=0.0081667,这样我们再次计算:

cost= 2 +
ceil(0.163333 * 1,112)
ceil(0.0081667 * 9745)
= 2 + 182 + 80 = 264

在Oracle9i的plan_table里面引入了两个新的列:
SQL> desc plan_table
Name Null? Type
----------------------------------------- -------- ----------------------------
STATEMENT_ID VARCHAR2(30)
TIMESTAMP DATE
REMARKS VARCHAR2(80)
OPERATION VARCHAR2(30)
OPTIONS VARCHAR2(255)
OBJECT_NODE VARCHAR2(128)
OBJECT_OWNER VARCHAR2(30)
OBJECT_NAME VARCHAR2(30)
OBJECT_INSTANCE NUMBER(38)
OBJECT_TYPE VARCHAR2(30)
OPTIMIZER VARCHAR2(255)
SEARCH_COLUMNS NUMBER
ID NUMBER(38)
PARENT_ID NUMBER(38)
POSITION NUMBER(38)
COST NUMBER(38)
CARDINALITY NUMBER(38)
BYTES NUMBER(38)
OTHER_TAG VARCHAR2(255)
PARTITION_START VARCHAR2(255)
PARTITION_STOP VARCHAR2(255)
PARTITION_ID NUMBER(38)
OTHER LONG
DISTRIBUTION VARCHAR2(30)
CPU_COST NUMBER(38)
IO_COST NUMBER(38)
TEMP_SPACE NUMBER(38)
ACCESS_PREDICATES VARCHAR2(4000)
FILTER_PREDICATES VARCHAR2(4000)

这里access_predicates列出访问索引是被使用了的条件,filter_predicates列出被忽略了的条件。


实验4

 

我们知道8i开始有一个和索引有关的参数:OPTIMIZER_INDEX_CACHING,官方关于这个参数的解释是:
OPTIMIZER_INDEX_CACHING lets you adjust the behavior of cost-based optimization to favor nested loops joins and IN-list iterators.
The cost of executing an index using an IN-list iterator or of executing a nested loops join when an index is used to access the inner table depends on the caching of
that index in the buffer cache. The amount of caching depends on factors that the optimizer cannot predict, such as the load on the system and the block access patterns of different users.

也就是说,这个参数仅仅影响nested loops和in list中的index的使用,我们在其他的部分介绍nested loops,现在现看看对In-list的影响:

默认情况optimizer_index_caching = 0

select
/*+ index(t1) */
small_vc
from
t1
where n1 = 5
and ind_pad = rpad('x',40)
and n2 in (1,6,18);


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=68 Card=60 Bytes=3480)
1 0 INLIST ITERATOR
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T1' (Cost=68 Card=60 Bytes=3480)
3 2 INDEX (RANGE SCAN) OF 'T1_I1' (NON-UNIQUE) (Cost=9 Card=60)


alter session set optimizer_index_caching = 25;

select
/*+ index(t1) */
small_vc
from
t1
where n1 = 5
and ind_pad = rpad('x',40)
and n2 in (1,6,18)
;


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=65 Card=60 Bytes=3480)
1 0 INLIST ITERATOR
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T1' (Cost=65 Card=60 Bytes=3480)
3 2 INDEX (RANGE SCAN) OF 'T1_I1' (NON-UNIQUE) (Cost=6 Card=60)


alter session set optimizer_index_caching = 50;

select
/*+ index(t1) */
small_vc
from
t1
where n1 = 5
and ind_pad = rpad('x',40)
and n2 in (1,6,18)
;

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=63 Card=60 Bytes=3480)
1 0 INLIST ITERATOR
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T1' (Cost=63 Card=60 Bytes=3480)
3 2 INDEX (RANGE SCAN) OF 'T1_I1' (NON-UNIQUE) (Cost=4 Card=60)

 

alter session set optimizer_index_caching = 75;

select
/*+ index(t1) */
small_vc
from
t1
where n1 = 5
and ind_pad = rpad('x',40)
and n2 in (1,6,18)
;

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=61 Card=60 Bytes=3480)
1 0 INLIST ITERATOR
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T1' (Cost=61 Card=60 Bytes=3480)
3 2 INDEX (RANGE SCAN) OF 'T1_I1' (NON-UNIQUE) (Cost=2 Card=60)


alter session set optimizer_index_caching = 100;

select
/*+ index(t1) */
small_vc
from
t1
where n1 = 5
and ind_pad = rpad('x',40)
and n2 in (1,6,18)
;

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=59 Card=60 Bytes=3480)
1 0 INLIST ITERATOR
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T1' (Cost=59 Card=60 Bytes=3480)
3 2 INDEX (RANGE SCAN) OF 'T1_I1' (NON-UNIQUE)

不是很清楚具体是怎么计算了,看上来好像是只影响Index部分的cost,比如原来的cost是9,当设置optimizer_index_caching =75之后,那么新的cost= trunc(9*0.25)=2。

8i引入的和index有关的另一个重要的参数是optimizer_index_cost_adj,我们知道在8i里面CBO是不知道单块读和多块读的区别的,而这个参数就是为了弥补这个问题,默认值100是说单块读和多块读的cost一样,当我们调小这个参数值以后,CBO认为单块读比多块读的cost小,否则如果调大,CBO会认为单块读比多块读cost大。optimizer_index_cost_adj的问题在于它并不是影响CBO对多块读的cost,而是影响CBO对单块读的cost,这其实是个有问题的逻辑,因为合理的思维是应该调整多块读的cost,所有有的时候可能会导致CBO本来选择了一个较好的索引,但调整了optimizer_index_cost_adj后会选择一个较差的索引。从这个角度来说9i的system statistics就是调整多块读的cost,所以system statistics是更加合理的,而且system statistics是可以在真实环境中收集信息的,所以也比我们估计optimizer_index_cost_adj来的合理。

分享到:
评论

相关推荐

    上市公司企业澄清公告数据(2001-2023年) .xlsx

    详细介绍及样例数据:https://blog.csdn.net/li514006030/article/details/143896457

    (源码)基于Java和MySQL的物联网环境监测系统.zip

    # 基于Java和MySQL的物联网环境监测系统 ## 项目简介 本项目是一个基于Java和MySQL的物联网环境监测系统,旨在通过采集、存储和分析环境数据,实现对环境的实时监测和管理。系统涵盖了数据采集、数据存储、数据发送、数据接收、数据备份和日志记录等多个模块,确保数据的完整性和系统的稳定性。 ## 项目的主要特性和功能 1. 数据采集模块 从指定的数据文件(如radwtmp)中读取原始数据,并将其封装成Environment对象。 将多个Environment对象存储到集合中,便于后续处理。 2. 数据存储模块 创建数据库表结构,用于存储环境数据。 将采集到的环境数据批量存储到MySQL数据库中,支持批量处理以优化性能。 3. 网络模块 客户端调用采集模块获取数据,并将数据发送至服务器。 服务器端接收客户端发送的数据,并调用存储模块将数据存入数据库。支持多线程处理,提高并发性能。

    中国2002-2021年31省份经济韧性测度三级指标数据【重磅,更新!】

    1、资源内容地址:https://blog.csdn.net/abc6838/article/details/143895777 2、数据特点:今年全新,手工精心整理,放心引用,数据来自权威,且标注《数据来源》,相对于其他人的控制变量数据准确很多,适合写论文做实证用 ,不会出现数据造假问题 3、适用对象:大学生,本科生,研究生小白可用,容易上手!!! 4、课程引用: 经济学,地理学,城市规划与城市研究,公共政策与管理,社会学,商业与管理

    TMS WEB Core v2.0.5.0 for Delphi 11 (D11.1) 下载

    TMS WEB Core v2.0.5.0 for Delphi 11 (D11.1) 下载仓库 简介 本仓库提供 TMS WEB Core v2.0.5.0 for Delphi 11 (D11.1) 的资源文件下载。TMS WEB Core 是一个强大的工具,专为 Delphi 开发者设计,帮助他们轻松构建现代化的 Web 应用程序。 资源文件信息 标题: TMS-WEB-Core-v2.0.5.0-for-Delphi-11-D11.1 描述: TMS_WEB_Core_v2.0.5.0_for_Delphi_11_D11.1 使用说明 下载资源文件: 点击仓库中的资源文件进行下载。 安装: 按照 TMS WEB Core 的官方安装指南进行安装。 开发: 使用 Delphi 11 进行 Web 应用程序的开发。 注意事项 请确保您已经安装了 Delphi 11 (D11.1) 版本。 在安装和使用过程中,请参考 TMS WEB Core 的官方文档以获取更多帮助。 联系我们 如果您在使用过程中遇到任何问题或有任何建议,请通过以下方式联系我们: 邮箱: support@exa

    PyCharm安装与基本配置指导

    内容概要:本文档是一份详细的PyCharm安装与基本配置教程,旨在帮助初学者轻松掌握从下载安装到运行首个Python程序的所有步骤。内容覆盖PyCharm的选择与下载、安装路径设定、环境变量配置以及首次启动后的各项重要设置,如主题更换、汉化、安装插件增强体验等,最后还简述了如何运行第一个程序。同时提供了丰富的配图辅助理解和操作。 适合人群:面向编程新手特别是对Python感兴趣的学习者。对于有一定Python基础但缺乏高效IDE使用经验的研发人员也有一定借鉴意义。 使用场景及目标:①快速熟悉PyCharm IDE的基本操作与环境搭建流程;②优化编码体验,学会利用插件提升效率;③为深入Python编程学习打下坚实的基础。 阅读建议:按照步骤执行操作时注意对比教程提供的图片与实际界面是否一致,如有疑问可参照文档给出的具体链接进一步探索相关资料。此外,虽然本文档主要针对PyCharm的社区版,高级用户也可以将其作为官方文档的补充参考材料。

    SQL 学习教程(入门到实践)

    本教程从基础开始,介绍了 SQL 的语法和常用操作,包括创建表、查询数据、更新与删除、聚合与连接查询,以及数据库完整性和索引。通过提供学习资源和练习任务,帮助您快速掌握 SQL 的核心技能,为数据库管理和数据分析奠定基础。

    人工智能开发项目深度学习项目源码带指导视频服饰关键点定位

    人工智能开发项目深度学习项目源码带指导视频服饰关键点定位提取方式是百度网盘分享地址

    vncviewer.exe

    vncviewer.exe

    java毕设项目之基于Java的校园消费点评系统(源码+说明文档+mysql).zip

    环境说明:开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7 数据库工具:Navicat 开发软件:eclipse/myeclipse/idea Maven包:Maven 浏览器:谷歌浏览器。 项目经过测试均可完美运行

    人工智能开发项目深度学习项目源码带指导视频令人拍案叫绝的WGAN

    人工智能开发项目深度学习项目源码带指导视频令人拍案叫绝的WGAN提取方式是百度网盘分享地址

    (源码)基于DevExpress框架的进销存管理系统.zip

    # 基于DevExpress框架的进销存管理系统 ## 项目简介 进销存管理系统是一个基于CS架构的应用程序,主要用于管理企业的采购、销售、库存等业务流程。系统采用DevExpress插件进行界面设计和数据展示,提供了丰富的功能模块,包括采购管理、供应商管理、销售管理、库存管理、客户管理、系统用户管理和商品管理。 ## 项目的主要特性和功能 1. 采购管理管理企业的采购订单,跟踪采购流程。 2. 供应商管理维护和管理供应商信息,包括供应商的详细资料和历史交易记录。 3. 销售管理管理销售订单,跟踪销售流程和客户需求。 4. 库存管理实时监控库存情况,管理库存的进出和调拨。 5. 客户管理维护和管理客户信息,包括客户的详细资料和历史交易记录。 6. 系统用户管理管理系统的用户账号和权限,确保系统的安全性和稳定性。 7. 商品管理管理商品信息,包括商品的详细资料和库存情况。 ## 安装使用步骤 ### 环境准备

    (源码)基于C语言和C++的简单网站留言评论系统.zip

    # 基于C语言和C++的简单网站留言评论系统 ## 项目简介 这是一个基于C语言和C++的简单网站留言评论系统,旨在通过学习和实践计算机入门到进阶的知识,实现一个功能完善的网站评论系统。项目分为初稿和中稿两部分,初稿使用C语言实现,中稿则在初稿的基础上,将编程语言切换到C++,并利用第三方库进行功能优化。 ## 项目的主要特性和功能 1. 前端界面通过HTML和CSS实现简洁的网页界面,用户可以浏览评论、发表新评论和查看回复。 2. JavaScript事件监听使用JavaScript监听用户的前端操作,如发表评论、点赞等,并向后端发送请求。 3. 后端处理使用C语言和C++编写服务器进程,处理前端请求,与数据库进行交互,并返回结果。 4. 数据库操作通过MySQL数据库存储评论数据,包括评论内容、评论回复等。 5. 多线程处理服务器进程使用多线程模式处理多个客户端的请求,提高处理效率。

    基于springboot的校园失物招领系统源码数据库文档.zip

    基于springboot的校园失物招领系统源码数据库文档.zip

    C# 学习教程(入门到实践)

    本教程涵盖了 C# 的基础语法、类与对象、继承与接口、文件操作、以及异步编程,通过实用示例和练习帮助您快速入门。C# 的强大功能和广泛应用,使其成为开发 Windows 应用程序、游戏(如 Unity)、Web API 和云服务的理想选择。

    《Linux操作系统实用教程(第2版)》- 配套软件

    《Linux 操作系统实用教程(第 2 版)》这本书是一本非常实用的书籍,它为读者提供了关于 Linux 操作系统的深入讲解和实用教程。在这本书中,读者可以学习到 Linux 操作系统的基本概念、命令行操作、文件系统管理、用户管理、进程管理等方面的知识。同时,这本书还提供了丰富的配套软件,这些软件可以帮助读者更好地学习和使用 Linux 操作系统。例如,书中可能会介绍一些常用的文本编辑器、编译器、调试器等软件,这些软件可以帮助读者在 Linux 环境下进行编程和开发。此外,书中还可能会介绍一些系统管理工具、网络工具等软件,这些软件可以帮助读者更好地管理和维护 Linux 系统。总之,《Linux 操作系统实用教程(第 2 版)——配套软件》是一本非常值得一读的书籍,它可以帮助读者更好地了解和掌握 Linux 操作系统。

    springboot286入校申报审批系统的设计与实现.zip

    论文描述:该论文研究了某一特定领域的问题,并提出了新的解决方案。论文首先对问题进行了详细的分析和理解,并对已有的研究成果进行了综述。然后,论文提出了一种全新的解决方案,包括算法、模型或方法。在整个研究过程中,论文使用了合适的实验设计和数据集,并进行了充分的实验验证。最后,论文对解决方案的性能进行了全面的评估和分析,并提出了进一步的研究方向。 源码内容描述:该源码实现了论文中提出的新的解决方案。源码中包含了算法、模型或方法的具体实现代码,以及相关的数据预处理、实验设计和性能评估代码。源码中还包括了合适的注释和文档,以方便其他研究者理解和使用。源码的实现应该具有可读性、可维护性和高效性,并能够复现论文中的实验结果。此外,源码还应该尽可能具有通用性,以便在其他类似问题上进行进一步的应用和扩展。

    基于springboot高校学术交流平台源码数据库文档.zip

    基于springboot高校学术交流平台源码数据库文档.zip

    Objective-C 学习教程(入门-高级-实践)

    本教程介绍了 Objective-C 的基础语法、面向对象编程、动态类型和 Block 特性,并提供了实用的练习和答案。通过这些内容,您可以快速掌握 Objective-C 的核心概念,为 macOS/iOS 开发打下扎实的基础。

    基于springboot校外兼职教师考勤管理系统源码数据库文档.zip

    基于springboot校外兼职教师考勤管理系统源码数据库文档.zip

    【重磅,更新!】中国城市空气污染站点数据,共170多万条记录(2014-2022年)

    1、资源内容地址:https://blog.csdn.net/abc6838/article/details/143895851 2、数据特点:今年全新,手工精心整理,放心引用,数据来自权威,且标注《数据来源》,相对于其他人的控制变量数据准确很多,适合写论文做实证用 ,不会出现数据造假问题 3、适用对象:大学生,本科生,研究生小白可用,容易上手!!! 4、课程引用: 经济学,地理学,城市规划与城市研究,公共政策与管理,社会学,商业与管理

Global site tag (gtag.js) - Google Analytics