前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >应用接入ES(一)-Springboot集成ES

应用接入ES(一)-Springboot集成ES

作者头像
叔牙
修改于 2021-12-24 03:42:34
修改于 2021-12-24 03:42:34
4.5K00
代码可运行
举报
运行总次数:0
代码可运行

Elasticsearch 是一个分布式的开源搜索和分析引擎,适用于所有类型的数据,包括文本、数字、地理空间、结构化和非结构化数据。Elasticsearch 在 Apache Lucene 的基础上开发而成,由 Elasticsearch N.V.(即现在的 Elastic)于 2010 年首次发布。Elasticsearch 以其简单的 REST 风格 API、分布式特性、速度和可扩展性而闻名。一句话来说,Elasticsearch就是专业做搜索的,支持各种复杂的检索。

那么我们有比较复杂的检索诉求的场景下,如果传统关系型数据库无法支持或者说支持成本特别高,那么就可以考虑使用Elasticsearch(以下简称ES)来作为这种场景的替代方案。

一、环境准备

1:安装ES6.8

下载安装包:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.8.1.zip

解压:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
unzip elasticsearch-6.8.1.zip

修改默认配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
## 修改jvm.options内存配置
-Xms512m-Xmx512m

## 修改elasticsearch.yaml网络访问限制,允许其他机器访问
network.host: 0.0.0.0

后台启动:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
./bin/elasticsearch -d

检查启动情况:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
curl http://x.x.x.x:9200

启动正常。

2:创建索引

创建索引配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
curl  -H 'Content-Type: application/json' -XPUT http://localhost:9200/reverse -d'{    
"settings" : {        
    "index" : {            
            "number_of_shards" : 3, 
            "number_of_replicas" : 2 
     }  
   }
}'

这里制定了3个分片和两个副本,可以不配置使用默认。

创建映射:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
curl -H 'Content-Type: application/json' -XPUT 'http://localhost:9200/reverse/_mapping/return_order' -d '{        
"properties" : {        
"a" : {         
 "type" : "date"        
        }
        ...
   }
}'

可以使用http://xxx.xxx.xxx.xxx:9200/reverse/_mapping/return_order查看配置的type映射内容。

二、应用集成ES

本篇我们只讲述应用集成ES完成基本crud的几种方式,对于业务数据同步到ES暂不做讲述。应用集成ES的方式大致有4种,在说具体实现方式之前引一个小插曲,看一下ES java api的一段话:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
We plan on deprecating the TransportClient in Elasticsearch 7.0 and removing it 
completely in 8.0. Instead, you should be using the Java High Level REST Client, 
which executes HTTP requests rather than serialized Java requests. The migrationguidedescribes all the steps needed to migrate.  The Java High Level REST Client currently has support for the more commonly usedAPIs, but there are a lot more that still need to be added. You can help us prioritiseby telling us which missing APIs you need for your application by adding a commentto this issue: Java high-level REST client completeness.

大致意思是ES7.0会废弃掉TransportClient(Netty基于tcp协议实现的客户端),8.0会完全移除,官方建议使用RestHighLevelClient基于http协议访问ES。

所以基于这个原因,应用集成ES按照通信协议维度,分别有以下实现方式:

  • TCP:

Jpa

ElasticSearchTemplate

  • Http

RestClient

RestHighLevelClient

Jpa是最传统的持久层框架此处不赘述,ES的Jpa由spring-data-elasticsearch实现,提供一些模板化的更新操作和查询,最大的缺点是不够灵活,对定制化操作不友好并且自定义实现有点繁杂。

ElasticSearchTemplate是类似于JdbcTemplate,也是spring-data-elasticsearch提供的对各种ES更新和查询操作的模板实现,相比ElasticsearchRepositoryapi更清晰易懂,除了支持通用的实现之外也能支持各种定制化的检索操作。

RestClient是低版本的Rest客户端,基于http协议实现,对于ES中各种操作也能够很好的支持,但是api相对复杂,无法提供更“java化”的交互,简单点说对于客户端与服务端的请求和响应棱角过明显,对于响应结果更偏向于程序自己解析和序列化。

RestHighLevelClient是基于低版本客户端RestClient实现的高亮Rest客户端,目前官方极力推荐使用RestHighLevelClient来访问ES,如果发现高版本RestClient缺失功能,则会降级到低版本RestClient来发送json请求。

接下来我们切入正题,Jpa和低版本RestClient这里不展开讲述,重点来看一下ElasticSearchTemplate和RestHighLevelClient这两种方式的实现。

1:ElasticSearchTemplate

增加ES相关配置,application.yml:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
spring:
  data:
      elasticsearch:
            cluster-name: elasticsearch
            cluster-nodes: host:9300 #tcp是9300      
            local: false      
            repositories:   
                 enable: false

引入依赖:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>transport</artifactId>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-client</artifactId>
</dependency>
<dependency>
    <groupId>org.elasticsearch.plugin</groupId>
    <artifactId>transport-netty4-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-elasticsearch</artifactId>
</dependency>

访问ES实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
## 自动注入ElasticSearchTemplate 
@Autowired private ElasticsearchTemplate elasticsearchTemplate;
## 查单个 
public ReturnEsDO getByReturnId(String returnId) {    
    SearchQuery query = new NativeSearchQueryBuilder()
        .withQuery(new QueryStringQueryBuilder(returnId)
        .field("returnId")).build();
    List<ReturnEsDO> list = this.elasticsearchTemplate.queryForList(query,ReturnEsDO.class);
    if(null == list || list.isEmpty()) {        
        log.warn("returnId={},result empty",returnId);        
        return null;    }    return list.get(0); 
    }
## 分页查询 
public Page<ReturnEsDO> queryPage(ReturnEsQueryParam param) {    
    String sortStr = param.getSort();    
    Sort sort = new Sort(SortEnum.DESC.getType()
        .equalsIgnoreCase(sortStr) ? Sort.Direction.DESC : Sort.Direction.ASC,"appliedTime"); 
    Pageable pageable = PageRequest.of(param.getPageNum() - 1,param.getPageSize(),sort);
    SearchQuery query = new NativeSearchQueryBuilder()            
        .withIndices(index)            
        .withTypes(type)            
        .withQuery(this.buildQuery(param))            
        .withPageable(pageable)            
        .build();    
    Page<ReturnEsDO> page = this.elasticsearchTemplate.queryForPage(query,ReturnEsDO.class);
    return page; }
## 新增doc 
public void save(ReturnEsDO returnEsDO) {    
    IndexQuery indexQuery = this.buildIndexQuery(returnEsDO);    
    String index = this.elasticsearchTemplate.index(indexQuery);    
    log.info("save success;param={},index={}",returnEsDO,index);
}
## 批量新增 
public void batchSave(List<ReturnEsDO> esDOList) {    
    List<IndexQuery> indexQueryList = esDOList.stream()            
        .map(this::buildIndexQuery)            
        .collect(Collectors.toList());   
    this.elasticsearchTemplate.bulkIndex(indexQueryList); 
}
## 删除文档 
public void delete(String returnId) {    
    DeleteQuery deleteQuery = new DeleteQuery();    
    deleteQuery.setQuery(QueryBuilders.matchQuery("returnId", returnId));   
    deleteQuery.setIndex(index);    
    deleteQuery.setType(type);    
    this.elasticsearchTemplate.delete(deleteQuery);    
    log.info("delete success;returnId={}",returnId); 
}
## 更新文档 
public void update(ReturnEsDO returnEsDO) {    
    try {       
     UpdateRequest updateRequest = new UpdateRequest()                
         .index(index)                
         .type(type)                
         .id(returnEsDO.getReturnId())                
         .doc(this.buildUpdateDoc(returnEsDO));        
     UpdateQuery updateQuery = new UpdateQueryBuilder()                
         .withIndexName(index)                
         .withType(type)                
         .withId(returnEsDO.getReturnId())                
         .withClass(ReturnEsDO.class)                
         .withUpdateRequest(updateRequest)                
         .build();        
     UpdateResponse response = this.elasticsearchTemplate.update(updateQuery);        
     log.info("update end;param={},response={}",returnEsDO,response);    
    } catch (Exception e) {        
           log.error("update occur error;param={}",returnEsDO,e);   
    } 
}

具体的构建查询和更新参数不展开描述。

2:RestHighLevelClient

该客户端是是目前官方推荐使用的RestClient。

增加ES相关配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
es:  
    host:    
        address: host    
        port: 9200    
        protocol:http

引入maven依赖:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>    
    <groupId>org.elasticsearch.client</groupId>    
    <artifactId>elasticsearch-rest-high-level-client</artifactId> 
</dependency> 
<dependency>    
    <groupId>org.elasticsearch</groupId>    
    <artifactId>elasticsearch</artifactId> 
</dependency>
<dependency>    
    <groupId>org.elasticsearch.client</groupId>    
    <artifactId>elasticsearch-rest-client</artifactId> 
</dependency>

增加RestHighLevelClient配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Configuration
public class ElasticsearchConfig {
    @Value("${es.host.address}")
    private String esHostAddress;

    @Value("${es.host.port}")
    private Integer esHostPort;

    @Value("${es.hot.protocol}")
    private String protocol;

    @Bean(destroyMethod = "close")
    public RestHighLevelClient restHighLevelClient() {
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost(esHostAddress, esHostPort, protocol)));
        return client;
    }
}

访问ES实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
## 注入Client
@Autowired
private RestHighLevelClient restHighLevelClient;

## 查询单条记录
public ReturnEsDO getByReturnId(String returnId) {
    try {
        GetRequest getRequest = new GetRequest(index, type, returnId);
        GetResponse response = this.restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
        Map<String, Object> map = response.getSourceAsMap();
        return this.transferMap2DO(map);
    } catch (Exception e) {
        log.error("ReturnRepository.getByReturnId occur error;returnId={}", returnId, e);
        return null;
    }
}

## 分页查询
public PageResp<ReturnEsDO> queryPage(ReturnEsQueryParam param) {
    try {
        SearchRequest request = new SearchRequest(index);
        QueryBuilder queryBuilder = this.buildQuery(param);
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(queryBuilder);
        sourceBuilder.size(param.getPageSize());
        sourceBuilder.from((param.getPageNum()-1)*param.getPageSize());
        String sortStr = param.getSort();
        sourceBuilder.sort("appliedTime", SortEnum.DESC.getType().equalsIgnoreCase(sortStr) ? SortOrder.DESC : SortOrder.ASC);
        sourceBuilder.trackTotalHits(true);
        request.source(sourceBuilder);
        SearchResponse response = this.restHighLevelClient.search(request, RequestOptions.DEFAULT);
        if (null == response || null == response.getHits()) {
            log.warn("ReturnEsRepository.queryPage response empty;param={}", param);
            return PageResp.wrap(0, 0, Collections.emptyList());
        }
        SearchHits result = response.getHits();
        int totalHits = (int) result.getTotalHits();
        if (totalHits <= 0) {
            log.warn("ReturnEsRepository.queryPage response find not hits;param={}", param);
            return PageResp.wrap(0, 0, Collections.emptyList());
        }
        List<ReturnEsDO> list = new ArrayList<>();
        for (SearchHit hit : result.getHits()) {
            ReturnEsDO esDO = JSON.parseObject(hit.getSourceAsString(), ReturnEsDO.class);
            list.add(esDO);
        }
        return PageResp.wrap(totalHits, this.calculateTotalPage(totalHits, param.getPageSize()), list);
    } catch (Exception e) {
        log.error("ReturnEsRepository.queryPage occur error;param={}", param, e);
        return PageResp.wrap(0, 0, Collections.emptyList());
    }
}

## 新增文档
public void save(ReturnEsDO returnEsDO) {
    try {
        IndexRequest indexRequest = new IndexRequest(index, type, returnEsDO.getReturnId()).source(JSON.toJSONString(returnEsDO), XContentType.JSON);
        IndexResponse response = this.restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        log.info("ReturnEsRepository.save success;param={},response={}", returnEsDO, response);
    } catch (Exception e) {
        log.error("ReturnEsRepository.save occur error;returnEsDO={}", JSON.toJSONString(returnEsDO), e);
    }
}

## 批量新增文档
public void batchSave(List<ReturnEsDO> esDOList) {
    try {
        BulkRequest request = new BulkRequest();
        for (ReturnEsDO esDO : esDOList) {
            IndexRequest indexRequest = new IndexRequest(index, type, esDO.getReturnId()).source(JSON.toJSONString(esDO), XContentType.JSON);
            request.add(indexRequest);
        }
        BulkResponse response = this.restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
        log.info("ReturnEsRepository.batchSave success;response={}", response);
    } catch (Exception e) {
        log.error("ReturnEsRepository.batchSave occur error;param={}", JSON.toJSONString(esDOList), e);
    }
}
## 删除文档
public void delete(String returnId) {
    try {
        DeleteRequest request = new DeleteRequest(index, type, returnId);
        DeleteResponse response = this.restHighLevelClient.delete(request, RequestOptions.DEFAULT);
        log.info("ReturnEsRepository.delete success;returnId={},response={}", returnId, response);
    } catch (Exception e) {
        log.error("ReturnEsRepository.delete occur error;returnId={}", returnId, e);
    }
}

## 更新文档
public void update(ReturnEsDO returnEsDO) {
    try {
        UpdateRequest updateRequest = new UpdateRequest()
                .index(index)
                .type(type)
                .id(returnEsDO.getReturnId())
                .doc(this.buildUpdateDoc(returnEsDO));
        UpdateResponse response = this.restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
        log.info("ReturnEsRepository.update end;param={},response={}", returnEsDO, response);
    } catch (Exception e) {
        log.error("ReturnEsRepository.update occur error;param={}", returnEsDO, e);
    }
}

三、容易踩到的坑

1.ElasticSearchTemplate方式端口问题

ElasticSearchTemplate通过tcp协议访问ES,端口默认是9300,容易写成9200(http访问端口)。

2.ElasticSearchTemplate分页查询问题

ElasticSearchTemplate#queryForPage分页查询从第0页开始,如果和mysql分页查询一样从第1页开始容易查不到数据。

3.Amazon Elasticsearch Service不支持tcp协议

如果公司用的是AWS提供的ES服务,那么在开发之前一定要确认好,因为Amazon的ES服务压根不支持tcp协议访问,所以Jpa和ElasticSearchTemplate这两种实现完全失效,如果一不小心在开发和测试环境都是用这两种方式编码和测试,那么很不幸,代码重写切换成RestClient或者高亮RestClient。

4.RestHighLevelClient端口问题

虽然RestHighLevelClient通过http方式访问ES,但是有的ES服务可能是http也可能是https,在配置host和端口的时候一定要注意,http默认端口是80,https默认端口是443,否则会出现服务连不上或者节点找不到等一系列问题。

5.RestHighLevelClient分页问题

RestHighLevelClient分页查询通过from和size属性指定,需要注意的是这里的from不是mysql查询中的pageNumber,而是类似offset起始位点,如果设置成查询页码,会出现查询数据错乱的问题。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 PersistentCoder 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
数据库:MySQL、SqlServer、Oracle对比
MySQL的核心程序是采用完全的多线程编程。并且是轻量级的进程,它可以灵活地为用户提供服务,而不过多的系统资源。
IT技术分享社区
2021/04/30
4K0
数据库:MySQL、SqlServer、Oracle对比
Oracle与Sql server的区别 一直搞不明白Oracle数据库和sql server的区别,今天我特意查资料把他们的区别整理出来
Oracle数据库:Oracle Database,又名Oracle RDBMS,或简称Oracle。是甲骨文公司的一款关系数据库管理系统。
阿强Wwlt
2018/08/01
5.3K0
Oracle 数据库、Microsoft SQL Server、MySQL 数据库三种常见数据库的区别深度剖析
Oracle 数据库、Microsoft SQL Server、MySQL 数据库是我们在项目开发过程中最为常见的三种关系型数据库。下面我们分别从不同的角度对这三种数据库做一个深度剖析和区分,便于我们在开发中更为熟练地选择合适的数据库工具。
白鹿第一帅
2021/03/02
1.4K0
Oracle 数据库、Microsoft SQL Server、MySQL 数据库三种常见数据库的区别深度剖析
sqlserver、Mysql、Oracle三种数据库的优缺点总结
一、sqlserver 优点: 易用性、适合分布式组织的可伸缩性、用于决策支持的数据仓库功能、与许多其他服务器软件紧密关联的集成性、良好的性价比等; 为数据管理与分析带来了灵活性,允许单位在快速变化
小小科
2018/05/02
2.8K0
sqlserver、Mysql、Oracle三种数据库的优缺点总结
针对我国——国产数据库进行分析
Oracle能在所有主流平台上运行(包括Windows),完全支持所有的工业标准,采用完全开放策略,可以使客户选择最适合的解决方案,对开发商全力支持。
用户10196776
2022/11/22
1.2K0
针对我国——国产数据库进行分析
数据库深度剖析:Oracle、Microsoft SQL Server、MySQL 三者有何区别?
Oracle 数据库、Microsoft SQL Server、MySQL 数据库是我们在项目开发过程中最为常见的三种关系型数据库。下面我们分别从不同的角度对这三种数据库做一个深度剖析和区分,便于我们在开发中更为熟练地选择合适的数据库工具。
白鹿第一帅
2022/11/30
1.6K0
数据库深度剖析:Oracle、Microsoft SQL Server、MySQL 三者有何区别?
企业是如何选择技术栈来做离线数仓
最近在跟一位粉丝聊天,聊起来了做离线数仓时该用那些技术栈。于是根据我的经验和参考一些资料于就有本篇文章。在这里我会分享三个案例,仅供参考。
大数据老哥
2021/02/04
9750
企业是如何选择技术栈来做离线数仓
其他数据库系统
DB2数据库系统DB2是IBM公司开发的关系型数据库系统,他有很多版本,如DB2工作版、DB2企业版、DB2个人版、DB2企业扩展版,其区别在于是否支持远程客户能力和分布式处理能力。
ellipse
2019/08/16
1.2K0
一个OLTP数据库居然打榜OLAP全球第一
坊间传来消息,OceanBase又一次打榜TPC全球第一。自从有过两次TPC-C第一之后,这第三次打榜也有点不新鲜了。不过这次可不是TPC-C,而是TPC-H。OceanBase以1526万QphH的性能总分创造了新的世界纪录,成绩是现在榜单第二名的10倍多!
用户1564362
2021/06/01
1.8K0
oracle数据库发展简史
1977年,Larry Ellison、Bob Miner和Ed Oates成立了咨询公司Software Development Laboratories,后来成为关系软件公司(RSI)。1983年,RSI成为Oracle Systems Corporation,后来成为Oracle Corporation。
DBA札记
2023/08/04
4840
oracle数据库发展简史
Oracle数据库系统
1. SQL SERVER 号称百万级数据(一个表的数据),但是其实做多20万条数据,超过20万条数据就用Oracle;
ellipse
2019/08/16
1.4K0
Oracle数据库系统
腾讯云数据库TDSQL ,数据库国产化替代的关键先生
在某大型银行的总部,该银行CEO王阳与CTO陈晓民坐在一间宽敞的会议室里,面对着一个满是图表和数据的大屏幕,讨论一个关键的挑战:如何用国产数据库来替代Oracle,更好地支撑公司业务的发展。
数据猿
2023/09/15
7740
腾讯云数据库TDSQL ,数据库国产化替代的关键先生
数据库性能评测真的很重要么?
国庆期间,最热闹的新闻莫过我国某数据库产品在TPC-C测试中勇夺性能第一的消息。该则消息的传播颇具争议性,引发了一场关于数据库的大讨论。事实上,数据库作为最重要的基础软件之一,在整个IT生态体系中具有举足轻重的作用,中国数据库产品在经历了四十余年的艰苦发展之后,能够夺得国际评测机构测试成绩第一固然可喜可贺,不过这也激发了我们进一步思考:
大数据在线
2019/10/25
8880
数据库性能评测真的很重要么?
常见的数据库有哪几种?[通俗易懂]
包括:MySQL、MariaDB(MySQL的代替品,英文维基百科从MySQL转向MariaDB)、Percona Server(MySQL的代替品)、PostgreSQL、Microsoft Access、Microsoft SQL Server、Google Fusion Tables。 FileMaker、Oracle数据库、Sybase、dBASE、Clipper、FoxPro、foshub。几乎所有的数据库管理系统都配备了一个开放式数据库连接(ODBC)驱动程序,令各个数据库之间得以互相集成。
全栈程序员站长
2022/10/02
2.2K0
一文了解华为Gauss数据库:开发历程、OLTP&OLAP特点、行式&列式存储,及与Oracle和AWS对比
数据库是计算机行业的基础核心软件,所有应用软件的运行和数据处理都要与其进行数据交互。2008年阿里提出“去IOE”,而10年之后,我们现在来看,发现Oracle的数据库是最难替换的。不仅是因为Oracle的数据库沉淀了大量的企业客户数据,更是因为数据库产品开发难度确实比较大。数据库的开发难度不亚于操作系统,属于整个IT架构的基础软件(数据库软件在操作系统之上,我们可以将其称为类中间层的基础软件)。而且数据库的开发需要与底层计算架构高度相关和耦合,是适配X86架构,还是适配ARM架构等等。
数据和云
2019/09/19
9.3K0
一文了解华为Gauss数据库:开发历程、OLTP&OLAP特点、行式&列式存储,及与Oracle和AWS对比
OceanBase,走入原生分布式数据库的无人区
在数字化时代,数据量呈现指数级增长,尤其是视频、图像、语音等数据急速积累。数据库,在整个数据价值体系中,承担着基石的作用。海啸一般的数据正在向我们迎面扑来,关于数据的整个计算、存储、应用技术体系,都必须经过大刀阔斧的改造,才能有效应对巨量的数据处理需求。那么,作为数据帝国的“重臣”,数据库该如何进化呢?答案是原生分布式数据库。
数据猿
2022/03/16
6780
OceanBase,走入原生分布式数据库的无人区
什么是oracle数据库实例_oracle库和实例区别
大家好,又见面了,我是你们的朋友全栈君。 数据库是一个数据的集合,不仅是指物理上的数据,也指物理、存储及进程对象的一个组合。Oracle是关系型数据库管理系统(RDBMS)。 二、实例(Instance) 数据库实例(也称为服务器Server)就是用来访问一个数据库文件集的一个存储结构及后台进程的集合。它使一个单独的数据库可以被多个实例访问(也就是ORACLE并行服务器– OPS)。实例和数据库的关系如下: —————————————————————————- | 实例1 SGA+进程 | 实例2 SGA+进程 | —————————————————————————- | 数据库(一组数据文件) | —————————————————————————- 决定实例的组成及大小的参数存储在init<sid>.ora文件中。 三、内部结构 表、列、数据类型(Table、Column、Datatype):Oracle中是以表的形式存储数据的,它包含若干个列;列是表的属性的描述;列由数据类型和长度组成;Oracle中定义的数据类型主要有CHAR、VARCHAR2、NUMBER、DATE、LONG、LOB、BFILE等 约束条件(Constraint) :表中以及表间可以存在一些数据上的逻辑关系、限制,也就是约束。Oracle中的约束主要有主键(PK)、外键(FK)、检查(CHECK)、唯一性(UNIQUE)等几种;拥有约束的表中每条数据均必须符合约束条件。 抽象数据类型(Abstract Datatype):可以利用CREATE TYPE命令创建自定义的抽象数据类型。 分区(Partition):可以利用分区将大表分隔成若干个小的存储单元,逻辑上仍然是一个完整的独立单一实体,以减小访问时数据的查找量,提高访问、存储效率。 用户(User):用户不是一个物理结构,但是它与数据库的对象拥有非常重要的关系–用户拥有数据库对象,以及对象的使用权。 模式(Schema):用户帐号拥有的对象集合称为模式。 索引(Index):数据库中每行记录的物理位置并不重要,Oracle为每条记录用一个ROWID来标识,ROWID记录了记录的准确位置。索引是供用户快速查找到记录的数据库结构。ORACLE8中有簇索引、表索引、位图索引三种索引形式。 簇(Cluster):经常被频繁引用的表可以在物理位置上被存储在一起,簇就是用来管理这种集中存储的。集中存储可以减少I/O次数,以达到性能的改善和提高。 散列簇(Hash Cluster):簇的另一种形式,这种簇中的数据要通过散列函数计算得出物理位置,它可以极大程度的提高等值查询的效率。 视图(View):可以理解为固化的查询或者没有数据存储的表,它是一组表的查询结果集合,对应用来说是独立的结构,除没有数据存储以外,拥有和表同样的属性。 序列(Sequence):一个唯一数值的序列生成器,它每次被引用后,自动递增。 过程、函数(Procedure、Function):编译存储在数据库中的一个PL/SQL程序段,可以被引用。函数返回调用者一个值,过程则不返回任何值。 包(Package):函数、过程的集合。包中可以包含不同的元素,可以是公有的也可以是私有的。 触发器(Trigger):触发器是一些过程或PL/SQL程序段,当一个特定的事件发生时,就会自动引发这些过程的执行。 同义词(Synonyms):在分布式数据库环境中,要完全识别一个对象,必须指出对象的主机、属主等信息,为了简化这一过程,可以对这些对象建立同义词,引用这些同义词时系统自动转义成对原始对象的引用。 权限、角色(Privilege、Role):为了引用数据库的对象,必须拥有这些对象的相应权限,角色是这些权限的集合,例如–DBA就是一个角色,它包括一组数据库权限。 数据库链路(Database Link):引用其他数据库的数据时,需要指明详细路径,链路就是详细路径的识别名。 四、内部存储结构 系统全局区(System Global Area,SGA):包括–数据块缓冲存储区(Data Block Buffer Area)、字典缓冲区(Dictionary Cache)、日志缓冲区(Redo Log Buffer)、SQL共享池(Shared SQL Pool)四部分。 正文区间(Context Area):每个用户都拥有自己的私有SQL区域,保存相关的SQL语句,直到语句相关的光标关闭为止。 程序全局区(Program Global Area,PGA):它是存储区中被单个用户进程所使用的区域,PGA不能共享。 五、后台进程(BACK
全栈程序员站长
2022/09/27
1.8K0
Oracle数据库应用系统结构
在安装、部署Oracle数据库软件时,需要根据不同应用结构(即硬件平台、操作系统平台)采用不同的方法(基本安装、高级安装),下面介绍几种常见的应用结构。
数据和云
2019/08/01
1.1K0
Oracle数据库应用系统结构
Oracle数据库,简述Oracle数据库备份和恢复
无论是哪种数据库都需要面临数据库数据备份和恢复的问题,使用UCACHE灾备云进行Oracle实时复制数据、搬迁数据功能来设计Oracle数据库备份和恢复解决方案,支持定时备份、实时备份,增量备份,同时可开展异地灾备,是Oracle数据库灾备/恢复的完美解决方案。
用户1289394
2021/05/06
2.3K0
数据库的七种武器
数据库的七种武器,是我在工作维护和接触到的七种常用数据库,包括4种常用的关系型数据库,3种常用nosql数据库。
wubx
2019/02/27
7630
数据库的七种武器
推荐阅读
相关推荐
数据库:MySQL、SqlServer、Oracle对比
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文