到目前为止,本专栏文章系列已经探索了使用Google和Amazon平台的云计算。 尽管它们的实现和结构不同,但这两个平台都可以实现快速且可扩展的部署。 它们使前所未有的快速,廉价地组装,测试,运行和维护Java应用程序成为可能。 但是,云并不是当今影响Java开发速度的唯一因素。 开源解决方案还使您能够快速组装软件应用程序,因为您不再需要编写太多代码。 编写自己的对象关系映射(ORM),日志记录或测试框架的日子已经一去不复返了。 这些问题在开源世界中一次又一次地得到了解决,而且面对它,这些解决方案几乎总是比您的解决方案更好。

关于本系列

自从Java技术首次出现以来,Java开发环境发生了根本变化。 得益于成熟的开源框架和可靠的租用部署基础架构,现在可以快速,廉价地组装,测试,运行和维护Java应用程序。 在本系列中,Andrew Glover探索了使这种新的Java开发范例成为可能的技术和工具的范围。

在Java开发的整个领域,开放源代码的创新使应用程序的组装更加容易。 Apache CouchDB,一个新的开源数据库(在撰写本文时为0.10.0版本)也不例外。 一旦安装并运行CouchDB,就很容易进行。 您只需使用HTTP连接即可使用它。 不需要JDBC驱动程序,也不需要第三方管理管理平台。 在本文中,我将向您介绍CouchDB,并向您展示如何快速使用它。 为了简化安装,您将利用Amazon的EC2平台。 然后,您将通过方便的Groovy模块与CouchDB通信。

面向文档的数据库

关系数据库从根本上统治着数据库市场。 但其他类型的数据库-包括对象orienteed和面向文档的数据库,这无论是从面向关系世界的巨大差别-使很多的感觉,不时。 CouchDB是一个面向文档的数据库。 它是无架构的,允许您以JavaScript对象表示法 (JSON)字符串的形式存储文档。

JSON格式

JSON是一种轻量级的数据交换格式,并且是Web应用程序的另一种格式。 它类似于XML,但冗长得多。 由于其轻巧的特性,它已成为Web的通用语言 。 请参阅相关的话题更多地了解JSON。

想想停车票。 这张纸包含许多项目,包括:

  • 违规日期
  • 时间
  • 那个地点
  • 您的车辆描述
  • 您的车牌信息
  • 罪行

票证上收集的格式和数据可能因司法管辖区而异。 即使在单个辖区中使用标准的停车票形式,票上捕获或未捕获的内容也很可能会有所不同。 例如,发布引用的人员可能没有填写时间,或者可能会省略车辆的制造商和型号,而是选择仅输入车牌详细信息。 该位置可能是两条街道(例如,Fourth和Lexington的交集)的组合,或者仅仅是固定地址(例如,19993 Main Street)。 但是所收集内容的粗略语义相似。

可以在关系数据库中对票证的数据点进行建模,但是细节有些繁琐。 例如,如何有效地在关系数据库中捕获相交? 并且在没有交叉路口的情况下,数据库中是否有第二个地址的空白字段(假设您以在各个列中捕获不同街道名称的方式对其建模)?

在这些情况下,关系数据库的抽象性可能会有点高。 所需信息已经以文件(票证)的形式存在。 为什么不只是将数据建模为文档,而文档不一定适合严格的关系模型,而是大致遵循高级模型的语义? 这就是CouchDB发挥作用的地方。 它使您可以灵活地对这些类型的域进行建模-作为一个独立的文档,其中不包含任何模式,但与其他文档具有大致相似的蓝图。

MapReduce

Google率先推出的MapReduce是用于处理海量数据集的概念性框架(请参阅参考资料 )。 它是针对使用大量计算机来解决分布式问题而进行高度优化的。 MapReduce是两个功能的组合:map和reduce。 映射功能旨在接收较大的输入并分成较小的部分(并将数据交给其他可以处理数据的进程)。 reduce函数旨在将map中的所有单个答案带入一个最终输出中。

使用CouchDB,您可以像在关系世界中一样搜索文档,文档属性,甚至关联文档。 您使用视图而不是SQL来执行此操作。 视图本质上是您以MapReduce风格编写(在JavaScript中)的函数; 也就是说,您最终编写了map函数和reduce函数。 这些功能协同工作以从文档中过滤或提取数据,或者非常有效地利用它们之间的关系。 实际上,只要基础文档没有更改,CouchDB就足够聪明地仅运行一次这些功能,这使得视图非常快。

CouchDB特别有趣的是它的设计。 CouchDB体现了Web本身的基本(并且非常成功)的概念。 它公开了一个完整的RESTful API,该API允许创建,查询,更新和删除文档,视图和数据库。 这使得CouchDB变得非常容易使用和使用。 您不需要驱动程序或其他平台即可开始开发:实质上是浏览器。 话虽这么说,但有许多库使使用CouchDB变得更加容易-但在幕后,它们只是通过HTTP利用RESTful概念。

CouchDB与Web本身一样,都是可扩展的。 它使用Erlang编写,Erlang是一种并发编程语言,支持构建分布式的,容错的,不间断的应用程序(请参阅参考资料 )。 该语言(现已作为开放源代码提供)由爱立信开发,并已在电信环境中得到广泛利用。

安装CouchDB,云风格

CouchDB的安装取决于您的操作系统。 如果您使用的是Windows®,则需要安装Cygwin,Microsoft C编译器以及许多其他相关的依赖项。 如果您使用的是Mac,则需要使用Macports。 但是,如果您在Linux®平台(例如Ubuntu)上运行,安装将变得更加简单。 但是并不是每个人都可以使用Ubuntu实例。 还是你

当然,您拥有一个方便的Ubuntu实例! 亚马逊的EC2是按需使用Ubuntu的相对便宜的方式。 因此,有了一点EC2的魔力,您就可以立即建立并运行CouchDB。 完成后,可以关闭电源,可以这么说。

首先,您需要找到一个可用作基本实例的EC2 AMI。 我最终使用了AMI ami-ccf615a5,它是Ubuntu 9.04的实例,它是在撰写本文时可用的最新版本。 (在您阅读本文时,9.10以及最可能的是较新的AMI都将可用。)使用Eclipse或AWS管理控制台,启动ami-ccf615a5实例。 确保设置了允许通过SSH访问的安全策略。 (尽管CouchDB使用HTTP,为简单起见,您将通过SSH隧道与之通信。)您还需要使用密钥对。 (如果需要指导,请参阅本系列的前两篇文章“ 可以借用EC2”和“ Easy EC2” 。)

启动Ubuntu 9.04的EC2实例后,需要使用ssh 。 (请记住,该实例可能需要一分钟左右才能完全启动,因此请耐心等待。)例如,我可以打开一个终端并通过ssh进入新创建的实例,如下所示:

aglover#> ssh -i .ec2/agkey.pem root@ec2-174-129-157-167.compute-1.amazonaws.com

我的AMI的DNS名称是ec2-174-129-157-167.compute-1.amazonaws.com,我引用的是名为agkey的密钥对。 您的DNS名称和密钥对无疑会有所不同。

在云化的Ubuntu实例上的命令提示符下,键入:

apt-get update

然后输入:

aptitude install couchdb

这些命令将自动安装CouchDB。 但是,请注意,他们不会安装最新版本。 如果需要最新版本,则需要从源代码安装CouchDB(请参阅参考资料 )。

命令完成执行后,您可以通过发出ps -eaf命令来检查CouchDB是否正在运行。 通过将ps输出管道传递给egrep查找一些在其路径中以couchdb运行的进程。 您应该在清单1所示的输出中看到一些内容:

清单1. CouchDB正在运行(折断以适合文章页面宽度的行)
couchdb   1820     1  0 00:54 ?        00:00:00 /bin/sh -e /usr/bin/couchdb -c /etc/couchdb/couch.ini -b -r 5 -p /var/run/couchdb.pid -o /
couchdb   1827  1820  0 00:54 ?        00:00:00 /bin/sh -e /usr/bin/couchdb -c /etc/couchdb/couch.ini -b -r 5 -p /var/run/couchdb.pid -o /
couchdb   1828  1827  0 00:54 ?        00:00:00 /usr/lib/erlang/erts-5.6.5/bin/beam -Bd -- -root /usr/lib/erlang -progname erl -- -home /v
couchdb   1836  1828  0 00:54 ?        00:00:00 heart -pid 1828 -ht 11

接下来,回到本地计算机,您将建立一个SSH隧道,使您可以访问在云上运行的CouchDB实例,就像它驻留在您自己的计算机上一样。 为此,请在本地计算机上打开一个新的终端会话,然后键入:

ssh -i your key -L 5498:localhost:5984 root@your AMI DNS

最后,在本地计算机上打开浏览器。 在位置栏中,输入http://127.0.0.1:5498/ 。 您应该在JSON中看到一条不错的欢迎消息,如下所示:

{"couchdb":"Welcome","version":"0.8.0-incubating"}

现在看来一切正常,您可以随时使用CouchDB。

与Groovy的RESTClient RESTful合作

休息

代表性状态转移(REST)是一种设计依赖于命名资源的松耦合Web应用程序的样式,例如以统一资源定位符(URL),统一资源标识符(URI)和统一资源名称(URN)的形式-而不是消息。 REST巧妙地在已经验证和成功的Web基础结构HTTP上搭载。 也就是说,REST利用了HTTP协议的各个方面,例如GET和POST请求。 这些请求很好地映射到标准业务应用程序需求,例如创建,读取,更新和删除(CRUD)。

由于CouchDB通过RESTful HTTP接口公开数据,因此使用CouchDB(通过浏览器已经看到)非常容易。 您想做的几乎所有事情都可以通过HTTP完成。

您可以在众多用于与HTTP交互的工具中进行选择。 当REST风格的接口工作,我的最爱之一是RESTClient扩展Groovy的HTTPBuilder(参见相关主题 )。 HTTPBuilder是Apache Commons Project流行的HTTPClient的包装,在HTTP POST,GET,PUT和DELETE的语法中增加了一些时髦的外观。 因为HTTPBuilder是使用Groovy构建的,并利用了Groovy,所以编写利用RESTful概念(例如与CouchDB进行通信)的脚本再简单不过了。

葡萄更容易,甚至更快

与Java开发2.0的一般主题(快速,便捷和免费(或廉价)一致)一样,当与诸如HTTPBuilder之类的库进行交互时,Groovy的方便的Grape(Groovy高级包装引擎或Groovy适应性包装引擎)功能尤其重要。 (请参阅参考资料 )。 Grape是一个依赖项管理器,它允许Groovy脚本和类在运行tieme时自动配置其特定的依赖项 。 这使使用各种开放源代码库变得轻而易举,因为您无需下载一系列JAR文件就可以开始编码。 例如,使用Grape,您可以编写Groovy脚本以使用HTTPBuilder,而无需事先拥有HTTPBuilder所需的JAR。 使用Grape,它们将在运行时(或编译时)下载(通过Apache Ivy)。

您可以通过注释和方法调用来利用Grape。 例如,您可以使用@Grab批注装饰方法或类声明。 在此批注中,您指定有关主要依赖项的一些相关元数据。 (通过常春藤的魔力,所有传递依赖也将被找出来)。 在运行时或编译时(以先到者为准),Grape下载这些依赖项并确保它们在您的类路径中。 如果已经下载了依赖项(例如,从以前的运行中),Grape仍然可以确保正确的JAR文件位于类路径中。

使用Groovy在CouchDB上轻松进行REST

必须先创建一个数据库,然后才能在CouchDB中创建任何文档。 要创建一个停车票数据库,请使用其RESTClient通过HTTPBuilder的专用域语言(DSL)发出HTTP PUT,如清单2所示。(本文示例的所有Groovy代码都可以下载 。)

清单2.创建一个CouchDB数据库
import static groovyx.net.http.ContentType.JSON
import groovyx.net.http.RESTClient@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.5.0-RC2')
def getRESTClient(){return new RESTClient("http://localhost:5498/")
}def client = getRESTClient()
def response = client.put(path: "parking_tickets",requestContentType: JSON, contentType: JSON)assert response.data.ok == true : "response from server wasn't ok"

CouchCB应该返回响应{"ok":true} 。 如清单2所示,在HTTPBuilder中,解析JSON并确保ok元素的值确实为true

接下来,是时候根据停车票主题创建一些文档了。 要对停车票进行建模,请记住,停车票有许多方面。 还请记住,由于这些是官员填写的实际表格,因此某些字段可能没有填写,甚至没有遵循规定的模式-考虑交叉点与确切位置。

使用HTTPBuilder,您可以通过HTTP PUT在CouchDB中创建一个文档(就像清单2中创建数据库一样)。 因为CouchDB使用JSON文档,所以您必须遵循JSON的名称-值格式。 您可以通过在Groovy中创建类似于地图的数据结构(HTTPBuilder将其转换为有效的JSON)来实现此目的。 清单3显示了如何:

清单3.通过RESTClient创建一个CouchDB文档
response = client.put(path: "parking_tickets/1234334325", contentType: JSON,requestContentType:  JSON,body: [officer: "Kristen Ree",location: "199 Baldwin Dr",vehicle_plate: "Maryland 77777",offense: "Parked in no parking zone",date: "2009/01/31"])assert response.data.ok == true : "response from server wasn't ok"
assert response.data.id == "1234334325" : "the returned ID didn't match"

清单3中发生了一些事情。首先,在为CouchDB文档发出PUT时,必须分配一个UUID。 CouchDB可以为您分配这些,也可以自己管理。 在清单3中,我只是做了一个( 1234334325 ); 因此,此UUID被附加到URL。 如果该UUID可用,则CouchDB将为其分配PUTed文档。 在我的put调用的body方面,请注意每个名称如何具有关联的值,就像正常映射一样。 例如,分配人员的名字是Kristen Ree ,票证的位置是199 Baldwin Dr.

清单4通过相同的技术在CouchDB中创建了另一个停车票:

清单4.另一个停车票
def id = new Date().time
response = client.put(path: "parking_tickets/${id}", contentType: JSON,requestContentType:  JSON,body: [officer: "Anthony Richards",location: "Walmart Parking lot",vehicle_plate: "Delaware 4433-OP",offense: "Parked in non-parking space",date: "2009/02/01"])assert response.data.ok == true : "response from server wasn't ok"
assert response.data.id == "${id}" : "the returned ID didn't match"

每次我通过RESTClient发出PUT时,都会断言JSON响应包含ok的真实值,并且我验证是否存在预期的id值。 请注意,在清单4中,我现在使用的是当前时间,而不是构成UUID,这不是万无一失的技术,但对于简单的交互就足够了。

当您在CouchDB中成功创建新文档时,它将以JSON响应,其中包含UUID和修订ID。 例如,此响应代表我在清单4中验证的JSON:

{"ok":true,"id":"12339892938945","rev":"12351463"}

您的idrev值无疑会有所不同。 请注意,我可以通过发出诸如response.data.id的调用来获取id值。

在CouchDB中,通过修订来跟踪文档,因此您可以返回到先前的文档版本(通过修订ID),就像在CVS或Subversion中一样。

CouchDB中的视图

现在,我已经创建了一些停车票(或者说CouchDB中的文档),是时候在CouchDB中创建视图了。 请记住,视图只是实际使用的MapReduce函数; 因此,您必须定义它们。 在许多情况下,您不需要reduce函数。 map函数可以为您处理大多数事情。 它确实听起来像。 例如,您实质上可以映射要过滤或查找的“事物”或方面。

我定义了两张票:一张是由Ree军官发行的,另一张是由Richards军官发行的。 例如,要查找由Ree官签发的所有票证,您可以编写一个映射函数,以相应地过滤officer财产。 然后将结果传递给CouchDB的emit函数。

使用CouchDB的管理界面:Futon

您可以通过CouchDB的RESTful API或被称为Futon的CouchDB的管理界面来定义视图。 Futon只是可从http:// localhost:5498 / _utils /获得的Web应用程序。 现在去那里,并且(假设您已经和我一起创建了数据库和文档),您应该会看到一个用于parking_tickets数据库的简单界面,如图1所示:

图1. Futon界面

如果选择parking_tickets数据库,则可以在最右边看到一个下拉列表(称为“ 选择视图 ” :)。 通过选择Custom query ...开始定义一个定制视图,如图2所示:

图2. Futon的视图选择界面

现在,Futon提供了一个界面,该界面可让您定义映射函数和归约函数。 (您可能需要单击查看代码链接)。 在Map文本框中,定义清单5所示的简单map函数:

清单5. CouchDB中的一个简单地图函数
function(doc) {if(doc.officer == "Kristen Ree"){emit(null, doc);}
}

如您所见,清单5中的map函数是用JavaScript定义的。 它所做的只是通过文档的officer属性过滤CouchDB数据库中的文档。 具体而言,仅当警务人员的姓名为Kristen Ree ,该函数才会将文档传递到emit 。 图3显示了在Futon中定义此函数的位置:

图3.创建一个MapReduce函数

接下来,要求您提供设计文档名称(输入by_name )和视图名称(输入officer_ree )。 这些名称将用作构建URL以便稍后调用该视图的方式(即http:// localhost:5498 / parking_tickets / _view / by_name / nzl_ree)。

现在,您可以通过HTTPBuilder使用此视图,如清单6所示:

清单6.调用新视图
response = client.get(path: "parking_tickets/_view/by_name/officer_ree", contentType: JSON,  requestContentType:  JSON)assert response.data.total_rows == 1response.data.rows.each{assert it.value.officer == "Kristen Ree"
}

此视图正确地返回一个仅包含一个文档的JSON响应:Officer Ree在1月31日发行的票证。清单6中的response对象通过相应地解析JSON隐藏了原始HTTP响应。 您可以通过在response对象的data属性上调用toString方法来查看原始JSON响应。 原始响应类似于清单7:

清单7.视图的原始结果
{"total_rows":1,"offset":0,"rows":[{"id":"1234334325","key":null,"value":{"_id":"1234334325","_rev":"4205717256","officer":"Kristen Ree","location":"199 Baldwin Dr","vehicle_plate":"Maryland 77777","offense":"Parked in no parking zone","date":"2009/01/31"}}]}

从返回的原始JSON文档中可以看到,HTTPBuilder轻松解析JSON的能力非常方便,因为它启用了类似于对象图的机制来评估各种属性及其对应的值。

出于演示目的,我将向数据库中添加更多文档。 为了继续研究示例,您应该使用代码download进行相同的操作。

CouchDB的emit函数用作各种组织者。 如果您不对map函数进行限制(如清单5所示 ),那么本质上来说emit将对传入的文档进行排序。 例如,如果要按日期获取所有票证(请考虑此处SQL的ORDER BY子句),则只需按文档的date字段emit ,如清单8所示:

清单8.一个更简单的map函数
function(doc) {emit(doc.date, doc);
}

清单9针对此视图发出HTTP GET(我给了它一个设计文档名称为dates和一个视图名称by_date )。

清单9.调用的另一个视图
response = client.get(path: "parking_tickets/_view/dates/by_date", contentType: JSON,requestContentType:  JSON)
assert response.data.total_rows == 4

清单9中的查询返回按照日期排序的parking_tickets数据库中的所有文档。 assert语句仅验证total_rows属性等于4 。 这是关键。 查看返回结果以及一些元数据(例如返回的文档数); 因此,这有助于在开始解析之前查看原始响应。 清单10显示了原始结果:

清单10.按日期排序的原始JSON文档
{"total_rows":4,"offset":0,"rows":[{"id":"85d4dbf45747e45406e5695b4b5796fe","key":"2009/01/30","value":{"_id":"85d4dbf45747e45406e5695b4b5796fe","_rev":"1318766781","officer":"Anthony Richards","location":"54th and Main","vehicle_plate":"Virginia FCD-4444","offense":"Parked in no parking zone","date":"2009/01/30"}},{"id":"1234334325","key":"2009/01/31","value":{"_id":"1234334325","_rev":"4205717256","officer":"Kristen Ree","location":"199 Baldwin Dr","vehicle_plate":"Maryland 77777","offense":"Parked in no parking zone","date":"2009/01/31"}},{"id":"12345","key":"2009/01/31","value":{"_id":"12345","_rev":"1479261876","officer":"Anthony Richards","location":"1893 Main St","vehicle_plate":"Maryland 4433-OP","offense":"Parked in no parking zone","date":"2009/01/31"}},{"id":"12339892938945","key":"2009/02/01","value":{"_id":"12339892938945","_rev":"12351463","officer":"Anthony Richards","location":"Walmart Parking lot","vehicle_plate":"Maine 4433-OP","offense":"Parked in non-parking space","date":"2009/02/01"}}]}

定义这样的视图的有趣之处在于,您可以随后传递一个键 -也就是说,您想要的是本质上emit函数的第一个值。 例如, 清单8中定义的视图实质上按日期排序。 如果您想按特定日期对其进行排序,则将该日期传递到视图查询中。 例如,仅出于娱乐目的,请在浏览器的位置框中输入以下URL:

http://localhost:5498/parking_tickets/_view/dates/by_date?key="2009/01/31"

然后,该视图仅返回1月31日发行的票证。您应该在浏览器窗口中看到一堆看起来像JSON的文本,与清单11相似。请注意,使用浏览器作为查询工具是一种特别简单的方法查看HTTP请求的原始JSON响应。

清单11. 1月31日只有两张票
{"total_rows":4,"offset":1,"rows":[{"id":"1234334325","key":"2009/01/31","value":{"_id":"1234334325","_rev":"4205717256","officer":"Kristen Ree","location":"199 Baldwin Dr","vehicle_plate":"Maryland 77777","offense":"Parked in no parking zone","date":"2009/01/31"}},{"id":"12345","key":"2009/01/31","value":{"_id":"12345","_rev":"1479261876","officer":"Anthony Richards","location":"1893 Main St","vehicle_plate":"Maryland 4433-OP","offense":"Parked in handicap zone without permit","date":"2009/01/31"}}]}

视图可以根据您的需要进行特定设置。 例如,通过一些JavaScript字符串操作,我可以编写一个查找在Main Street上任何地方发行的票证的清单,如清单12所示:

清单12.带有一些字符串魔术的另一个视图
function(doc) {if(doc.location.toLowerCase().indexOf('main') > 0){emit(doc.location, doc);}
}

从清单12中可以看到,如果任何文档的location元素包含main ,那么该文档将传递给emit函数。 请记住,此搜索范围很广。 如果文档的location包含诸如Germaine Street类的字符串,则也会返回该字符串。 对于我定义的少量票证,该视图将返回清单13中所示的结果:

清单13.按大街过滤的结果
{"total_rows":2,"offset":0,"rows":[{"id":"123433432asdefasdf4325","key":"4th and Main","value":{"_id":"123433432asdefasdf4325","_rev":"498239926","officer":"Chris Smith","location":"4th and Main","vehicle_plate":"VA FGA-JD33","offense":"Parked in no parking zone","date":"2009/02/01"}},{"id":"123433432223e432325","key":"54 and Main","value":{"_id":"123433432223e432325","_rev":"841089995","officer":"Kristen Ree","location":"54 and Main Street","vehicle_plate":"Maryland 77777","offense":"Parked in no parking zone","date":"2009/02/02"}}]}

请注意,JSON响应包含一个key元素,该元素描述了发出特定文档的原因。 此类信息非常有帮助。 还要注意,一直以来,在我定义的各种故障单中发现的数据都有些不一致:有些位置是精确的,而有些则不是。 尽管此数据可以存储在关系数据库中,但也非常适合面向文档的模型,您不觉得吗? 另外,借助Groovy的强大功能和HTTPBuilder轻松解析JSON的能力,获取数据非常容易(比原始JDBC容易得多)。

CouchDB作为Web的数据库

CouchDB特别有趣,因为它很容易使用。 关系数据库也很容易,但是如果您已经熟悉使用Web浏览器,那么该数据库的优点就是可以使用其API。 而且,由于CouchDB的RESTful API,您可以通过很酷的框架(例如HTTPBuilder的RESTClient与其通信。 您也不限于HTTPBuilder。 许多Java库都试图简化CouchDB的使用。 一个是特别看好的是jcouchdb(见相关信息 ),这从它所有的REST风格的烦躁和JSON岬盾牌你,让你在文档和视图Java语言编程工作。

请继续关注下个月的专栏文章,我将在这里返回到Google App Engine。 秉承开放创新的精神,新的框架不断涌现,这些框架促进了Google App Engine的开发和部署。 您将看到其中之一如何使Google的云平台上的Java开发2.0变得更加容易。


翻译自: https://www.ibm.com/developerworks/java/library/j-javadev2-5/index.html

hbase和couchdb_使用CouchDB和Groovy的RESTClient进行REST相关推荐

  1. 使用Hadoop MapReduce进行大数据分析

    Google在2001年推出图片搜索功能时,拥有2.5亿张索引图片. 不到十年后,这家搜索巨头就索引了超过100亿张图片. 每分钟有35个小时的内容上传到YouTube. 据说Twitter平均每天处 ...

  2. HBase数据库原理解析

    文章目录 1.HBase 数据库介绍 1.1产生背景 1.2简介 1.3表结构逻辑视图 1.3.1行键(RowKey) 1.3.2列簇(Column Family) 1.3.3时间戳(TimeStam ...

  3. HBase数据库原理介绍

    1.HBase 数据库 1.1.产生背景 自 1970 年以来,关系数据库用于数据存储和维护有关问题的解决方案.大数据的出现后,好多公司实现处理大数据并从中受益,并开始选择像 Hadoop 的解决方案 ...

  4. SQL与NoSQL的区别 以MySQL与MongoDB为例

    异同对比 1.语言和结构层面 SQL数据库,是基于表的,并且用结构化语言也就是SQL来定义和操纵数据.一方面,这是非常强大的:SQL是最通用和最广泛使用的选项之一,使其成为一个安全的选择,尤其适用于复 ...

  5. python创建数据库表_Python 操作数据库(1)SQL基础

    一.数据库 关系型数据库 常见的关系型数据库:SQL Server.MySql.MariaDB.SQLite.ORACLE.PostgreSQL等 非关系型数据库 常见的非关系型数据看:MongoDB ...

  6. 数据库mysql性能优化-学习笔记

    数据库mysql性能优化 1. 数据库设计范式 2. 常见关系数据库 3. MySQL 的版本 4. mysql存储计划 5 . mysql查询配置 和 设置配置 6 . mysql基本参数 7 .m ...

  7. 笔记12 SQL优化

    笔记12 性能与SQL优化 1.性能优化 复习一下什么是性能: DB/SQL 优化是业务系统性能优化的核心 2.关系数据库 MySQL 什么是关系数据库 数据库设计范式 常见关系数据库 SQL 语言 ...

  8. 使用 NoSQL 数据库提供云级别数据可伸缩性

    探索云和 NoSQL 数据库设计基础 在提及数据库扩展性时,人们就会想到相对低成本的.高性能的 NoSQL(不仅是 SQL)数据库,它包含一些非常有用的特性:水平可伸缩性.对弱一致性模型的支持.更灵活 ...

  9. JAVA_基础部分_综合篇

    JVM (1) 基本概念: JVM是可运行Java代码的假想计算机 ,包括一套字节码指令集.一组寄存器.一个栈.一个垃圾回收,堆 和 一个存储方法域.JVM 是运行在操作系统之上的,它与硬件没有直接的 ...

最新文章

  1. 打印从1到最大的n位数
  2. 在决策树类相关算法中,一个接点的基尼系数通常是大于还是小于他的父节点?是总是大于还是总是小于?
  3. 《C++ primer》--第1,2章小结
  4. 大学python用什么教材-python大学里用哪本教材比较好?
  5. 设计模式 之 代理模式
  6. 网工路由基础(7)策略路由PBR
  7. 用putty中的pscp命令拷贝文件
  8. JS 键盘监听事件 enter 13
  9. 京东健康APP内测版已上线各大安卓应用商店
  10. 1 Oracle数据库环境搭建
  11. hdu 3951 博弈
  12. 虚拟机下liunx安装jdk
  13. 使用计算机录制声音10,win10怎么录音的同时录电脑声音怎么办
  14. 【Unity】入门级Unity安装教程
  15. Vue入门(Vue.js,库与框架,MVVM,BootCDN,Vue入门,数据双向绑定,vue事件,生命周期,钩子函数 )
  16. HiWork告诉你:拿什么来拯救你,我的时间
  17. animated-rotate
  18. Luogu-P2015 二叉苹果树
  19. 安卓8.0-MT6763平台 st7701s-MIPI转RGB屏调试
  20. Oracle用OEM和命令行方式创建用户及表空间

热门文章

  1. 如何推广eBay门店?
  2. 数控程序必须经过校验和试切才能正式加工
  3. python简答题及答案查询公众号和软件_大学慕课答案免费查询公众号
  4. pythonhtml正文_python如何发送带有附件、正文为HTML的邮件
  5. VsCode设置快捷输入
  6. TextMesh Pro 的图文混排功能:插入自定义表情图
  7. [Storm]分布式单词计数(一)一个简单的storm demo
  8. 064.django之模型层单表查询
  9. c#process的详细用法
  10. java replaceall()的用法_Java replaceAll的用法