文本数据怎么批量导入elasticsearch官网

收藏,2.9k 浏览
之前测试了
这里我们使用和之前完全相同的测试数据,来测试 elasticsearch 存储时间序列的表结构选择问题。
一个点一个doc的表结构
同样我们以最简单的表结构开始。在elasticsearch中,先要创建index,然后index下有mapping。所谓的mapping就是表结构的概念。建表的配置如下:
settings = {
'number_of_shards': 1,
'number_of_replicas': 0,
'index.query.default_field': 'timestamp',
'index.mapping.ignore_malformed': False,
'index.mapping.coerce': False,
'index.query.parse.allow_unmapped_fields': False,
mappings = {
'testdata': {
'_source': {'enabled': False},
'_all': {'enabled': False},
'properties': {
'timestamp': {
'type': 'date',
'index': 'no',
'store': False,
'dynamic': 'strict',
'doc_values': True,
'fielddata': {
'format': 'doc_values'
'vAppid': {
'type': 'string',
'index': 'no',
'store': False,
'dynamic': 'strict',
'doc_values': True,
'fielddata': {
'format': 'doc_values'
'iResult': {
'type': 'string',
'index': 'no',
'store': False,
'dynamic': 'strict',
'doc_values': True,
'fielddata': {
'format': 'doc_values'
'vCmdid': {
'type': 'string',
'index': 'no',
'store': False,
'dynamic': 'strict',
'doc_values': True,
'fielddata': {
'format': 'doc_values'
'dProcessTime': {
'type': 'integer',
'index': 'no',
'store': False,
'dynamic': 'strict',
'doc_values': True,
'fielddata': {
'format': 'doc_values'
'totalCount': {
'type': 'integer',
'index': 'no',
'store': False,
'dynamic': 'strict',
'doc_values': True,
'fielddata': {
'format': 'doc_values'
表结构虽然没有做按时间段打包的高级优化,但是一些es相关的设置是特别值得注意的。首先_source被关闭了,这样原始的json文档不会被重复存储一遍。其次_all也被关闭了。而且每个字段的store都是False,也就是不会单独被存储。之前测试mongodb的时候,所有字段都没有建索引的,所以为了公平起见,这里把索引都关了。这些都关掉了,那么数据存哪里了?存在doc_values里。doc_values用于在做聚合运算的时候,根据一批文档id快速找到对应的列的值。doc_values在磁盘上一个按列压缩存储的文件,非常高效。
那么800多万行数据导入之后,磁盘占用情况如何?
size: 198Mi (198Mi)
docs: 8,385,335 (8,385,335)
非常惊人,838万行在mongodb里占了3G的磁盘空间,导入es居然只占用了198M。即便把所有维度字段的索引加上膨胀也非常小。
size: 233Mi (233Mi)
docs: 8,385,335 (8,385,335)
那么查询效率呢?
'timestamp': {
'terms': {
'field': 'timestamp'
'totalCount': {'sum': {'field': 'totalCount'}}
res = es.search(index="wentao-test1", doc_type='testdata', body=q, search_type='count')
同样是按时间聚合,取得同周期的totalCount之和。查询结果为:
{u'_shards': {u'failed': 0, u'successful': 1, u'total': 1},
u'aggregations': {u'timestamp': {u'buckets': [{u'doc_count': 38304,
u'key': 0,
u'key_as_string': u'T22:05:00.000Z',
u'totalCount': {u'value': }},
{u'doc_count': 38020,
u'key': 0,
u'key_as_string': u'T22:06:00.000Z',
u'totalCount': {u'value': }},
{u'doc_count': 37865,
u'key': 0,
u'key_as_string': u'T22:01:00.000Z',
u'totalCount': {u'value': }},
{u'doc_count': 37834,
u'key': 0,
u'key_as_string': u'T22:04:00.000Z',
u'totalCount': {u'value': }},
{u'doc_count': 37780,
u'key': 0,
u'key_as_string': u'T22:09:00.000Z',
u'totalCount': {u'value': }},
{u'doc_count': 37761,
u'key': 0,
u'key_as_string': u'T22:07:00.000Z',
u'totalCount': {u'value': }},
{u'doc_count': 37738,
u'key': 0,
u'key_as_string': u'T22:08:00.000Z',
u'totalCount': {u'value': }},
{u'doc_count': 37598,
u'key': 0,
u'key_as_string': u'T22:00:00.000Z',
u'totalCount': {u'value': }},
{u'doc_count': 37541,
u'key': 0,
u'key_as_string': u'T22:02:00.000Z',
u'totalCount': {u'value': }},
{u'doc_count': 37518,
u'key': 0,
u'key_as_string': u'T22:03:00.000Z',
u'totalCount': {u'value': }}],
u'doc_count_error_upper_bound': 0,
u'sum_other_doc_count': 8007376}},
u'hits': {u'hits': [], u'max_score': 0.0, u'total': 8385335},
u'timed_out': False,
u'took': 1033}
只花了1秒钟的时间,之前这个查询在mongodb里需要花9秒。那么是不是因为elasticsearch是并行数据库所以快呢?我们之前在创建index的时候故意指定了shard数量为1,所以这个查询只有一个机器参与的。为了好奇,我又试验了以下6个分片的。在分片为6的时候,总尺寸为259M(含索引),而上面那个查询只需要200ms。当然这里测试的时候使用的mongodb和es的机器不完全一样,也许是因为硬件原因呢?
第二个查询要复杂一些,按vAppid过滤,然后按timestamp和vCmdid两个维度聚合。查询如下:
'query': {
'constant_score': {
'filter': {
'must_not': {
'vAppid': ''
'timestamp': {
'terms': {
'field': 'timestamp'
'vCmdid': {
'terms': {
'field': 'vCmdid'
'totalCount': {'sum': {'field': 'totalCount'}}
res = es.search(index="wentao-test3", doc_type='testdata', body=q, search_type='count')
constant_score跳过了score阶段。查询结果如下:
{u'_shards': {u'failed': 0, u'successful': 1, u'total': 1},
u'aggregations': {u'timestamp': {u'buckets': [{u'doc_count': 38304,
u'key': 0,
u'key_as_string': u'T22:05:00.000Z',
u'vCmdid': {u'buckets': [{u'doc_count': 7583,
u'key': u'10000',
u'totalCount': {u'value': }},
{u'doc_count': 4122, u'key': u'19', u'totalCount': {u'value': 41463.0}},
{u'doc_count': 2312, u'key': u'14', u'totalCount': {u'value': 41289.0}},
{u'doc_count': 2257, u'key': u'18', u'totalCount': {u'value': 57845.0}},
{u'doc_count': 1723,
u'key': u'1002',
u'totalCount': {u'value': 33844.0}},
{u'doc_count': 1714,
u'key': u'2006',
u'totalCount': {u'value': 33681.0}},
{u'doc_count': 1646,
u'key': u'2004',
u'totalCount': {u'value': 28374.0}},
{u'doc_count': 1448, u'key': u'13', u'totalCount': {u'value': 32187.0}},
{u'doc_count': 1375, u'key': u'3', u'totalCount': {u'value': 32976.0}},
{u'doc_count': 1346,
u'key': u'2008',
u'totalCount': {u'value': 45932.0}}],
u'doc_count_error_upper_bound': 0,
u'sum_other_doc_count': 12778}},
... // ignore
{u'doc_count': 37518,
u'key': 0,
u'key_as_string': u'T22:03:00.000Z',
u'vCmdid': {u'buckets': [{u'doc_count': 7456,
u'key': u'10000',
u'totalCount': {u'value': }},
{u'doc_count': 4049, u'key': u'19', u'totalCount': {u'value': 39884.0}},
{u'doc_count': 2308, u'key': u'14', u'totalCount': {u'value': 39939.0}},
{u'doc_count': 2263, u'key': u'18', u'totalCount': {u'value': 57121.0}},
{u'doc_count': 1731,
u'key': u'1002',
u'totalCount': {u'value': 32309.0}},
{u'doc_count': 1695,
u'key': u'2006',
u'totalCount': {u'value': 33299.0}},
{u'doc_count': 1649,
u'key': u'2004',
u'totalCount': {u'value': 28429.0}},
{u'doc_count': 1423, u'key': u'13', u'totalCount': {u'value': 30672.0}},
{u'doc_count': 1340,
u'key': u'2008',
u'totalCount': {u'value': 45051.0}},
{u'doc_count': 1308, u'key': u'3', u'totalCount': {u'value': 32076.0}}],
u'doc_count_error_upper_bound': 0,
u'sum_other_doc_count': 12296}}],
u'doc_count_error_upper_bound': 0,
u'sum_other_doc_count': 8007376}},
u'hits': {u'hits': [], u'max_score': 0.0, u'total': 8385335},
u'timed_out': False,
u'took': 2235}
查询只花了2.2秒,而之前在mongodb上花了21.4秒。在6个shard的index上跑同样的查询,只需花0.6秒。
一个时间段打包成一个doc
和之前 MongoDB 的 _._._._.v 的结构一样,数据按照维度嵌套存放在内部的子文档里。
表结构如下
mappings = {
'testdata': {
'_source': {'enabled': False},
'_all': {'enabled': False},
'properties': {
'max_timestamp': {
'type': 'date',
'index': 'not_analyzed',
'store': False,
'dynamic': 'strict',
'doc_values': False,
'fielddata': {
'format': 'disabled'
'min_timestamp': {
'type': 'date',
'index': 'not_analyzed',
'store': False,
'dynamic': 'strict',
'doc_values': False,
'fielddata': {
'format': 'disabled'
'count': {
'type': 'integer',
'index': 'no',
'store': False,
'dynamic': 'strict',
'doc_values': False,
'fielddata': {
'format': 'disabled'
'sum_totalCount': {
'type': 'integer',
'index': 'no',
'store': False,
'dynamic': 'strict',
'doc_values': False,
'fielddata': {
'format': 'disabled'
'sum_dProcessTime': {
'type': 'integer',
'index': 'no',
'store': False,
'dynamic': 'strict',
'doc_values': False,
'fielddata': {
'format': 'disabled'
'_': { # timestamp
'type': 'nested',
'properties': {
'd': {'type': 'date', 'index': 'not_analyzed', 'store': False, 'fielddata': {'format': 'fst'}},
'c': {'type': 'integer', 'index': 'not_analyzed', 'store': False, 'fielddata': {'format': 'fst'}},
'0': {'type': 'integer', 'index': 'not_analyzed', 'store': False, 'fielddata': {'format': 'fst'}},
'1': {'type': 'integer', 'index': 'not_analyzed', 'store': False, 'fielddata': {'format': 'fst'}},
'_': { # vAppid
'type': 'nested',
'properties': {
'd': {'type': 'string', 'index': 'not_analyzed', 'store': False, 'fielddata': {'format': 'fst'}},
'_': { # iResult
'type': 'nested',
'properties': {
'd': {'type': 'string', 'index': 'not_analyzed', 'store': False, 'fielddata': {'format': 'fst'}},
'_': { # vCmdid
'type': 'nested',
'properties': {
'd': {'type': 'string', 'index': 'not_analyzed', 'store': False, 'fielddata': {'format': 'fst'}},
'v': { # values
'type': 'nested',
'properties': {
'0': {'type': 'integer', 'index': 'not_analyzed', 'store': False, 'fielddata': {'format': 'fst'}},
'1': {'type': 'integer', 'index': 'not_analyzed', 'store': False, 'fielddata': {'format': 'fst'}}
表结构的要点是一对nested的嵌套文档。nested的成员必须打开doc_values或者index中的一项,否则数据不会被保存。因为doc_values更占空间,所以我们选择了不存doc values。
在 MongoDB 里的数据
"sharded" : false,
"primary" : "shard2_RS",
"ns" : "wentao_test.sparse_precomputed_no_appid",
"count" : 39,
"size" : 2.68435e+08,
"avgObjSize" : 6.88294e+06,
"storageSize" : 2.75997e+08,
"numExtents" : 3,
"nindexes" : 1,
"lastExtentSize" : 1.58548e+08,
"paddingFactor" : 1.0000,
"systemFlags" : 1,
"userFlags" : 1,
"totalIndexSize" : 8176,
"indexSizes" : {
"_id_" : 8176
"ok" : 1.0000,
"$gleStats" : {
"lastOpTime" : Timestamp(, 3),
"electionId" : ObjectId("54c9f324adaa0bd054140fda")
只有39个文档,尺寸是270M。数据导入到es之后
size: 74.6Mi (74.6Mi)
docs: 9,355,029 (9,355,029)
文档数变成了935万个,因为子文档在es里也算成文档的,尺寸只有74M。查询条件如下
'expanded_timestamp': {
'nested' : {
'path': '_'
'grouped_timestamp': {
'terms': {
'totalCount': {
'field': '_.0'
res = es.search(index="wentao-test4", doc_type='testdata', body=q, search_type='count')
注意 _.0 是预先计算好的同周期的 totalCount sum。嵌套的维度字段排序是 timestmap =& vAppid =& iResult =& vCmdid =& values (0 as toalCount, 1 as dProcessTime)。
{u'_shards': {u'failed': 0, u'successful': 1, u'total': 1},
u'aggregations': {u'expanded_timestamp': {u'doc_count': 743,
u'grouped_timestamp': {u'buckets': [{u'doc_count': 8,
u'key': 0,
u'key_as_string': u'T22:09:00.000Z',
u'totalCount': {u'value': }},
... // ignore
{u'doc_count': 1,
u'key': 0,
u'key_as_string': u'T22:59:00.000Z',
u'totalCount': {u'value': 83009.0}}],
u'doc_count_error_upper_bound': 0,
u'sum_other_doc_count': 0}}},
u'hits': {u'hits': [], u'max_score': 0.0, u'total': 39},
u'timed_out': False,
u'took': 56}
查询只花了0.056秒。使用预先计算的值并不公平。使用原始的值计算也是可以做到的:
'per_id': {
'terms': {
'field': '_uid'
'expanded_timestamp': {
'nested' : {
'path': '_'
'grouped_timestamp': {
'terms': {
'expanded_vAppid': {
'nested' : {
'path': '_._._._.v'
'totalCount': {
'field': '_._._._.v.0'
这里使用了多级展开,最后对 _._._._.v.0 求和。计算的结果和 _.0 求和是一样的。花的时间是0.548秒。
然后再来测一下按vAppid过滤,同时按时间和vCmdid两个维度聚合的查询。这个写起来有一些变态:
'expanded_timestamp': {
'nested' : {
'path': '_'
'grouped_timestamp': {
'terms': {
'expanded_to_vAppid': {
'nested' : {
'path': '_._'
'vAppid_not_empty': {
'filter': {
'must_not': {
'_._.d': ''
'expanded_to_vCmdid': {
'nested' : {
'path': '_._._._'
'ts_and_vCmdid': {
'terms': {'field': '_._._._.d', 'size': 0}, # _._._._.d is vCmdid
'expanded_to_values': {
'nested' : {
'path': '_._._._.v'
'totalCount': {
'field': '_._._._.v.0'
查询的速度是3.2秒。比原始格式保存的方式查起来要慢。但是实际情况下,预先计算的值是更可能被使用的,这种需要拆开原始的value的情况很少。
ElasticSearch 就像闪电一样快。
原始格式保存,占用 198M(mongodb是3G),查询1秒(mongodb是9秒)
打包格式保存,占用 74M(mongodb是270M),查询0.54秒(mongodb是7.1秒)
打包格式在原始值要完全展开的时候稍微比原始格式要慢,但是打包可以很方便的存储预聚合的值,那么大部分时候读取甚至是0.05秒这个级别的。
如果我们可以用74M,存储880万个点。那么有2T硬盘,可以存多少数据呢?很多很多……不但可以存进去读出来,更重要的是es还可以帮我们在服务器端完成按需聚合,从不同维度快速展示数据。
你可能感兴趣的文章
10 收藏,1.7k 浏览
8 收藏,854 浏览
3 收藏,638 浏览
不要错过 TA 的任何更新
如果这篇文章对你有帮助,记得点赞收藏哦,你的支持是我们的动力 ^___^
本文隶属于专栏
I write code
分享到微博?
与我们一起探索更多的未知
专业的开发者技术社区,为用户提供多样化的线上知识交流,丰富的线下活动及给力的工作机会
加入只须一步
举报理由:
推广(招聘、广告、SEO 等)方面的内容
带有人身攻击、辱骂、仇恨等违反条款的内容
与已有问题重复(请编辑该提问指向已有相同问题)
内容质量差,或不适合在本网站出现
答非所问,不符合答题要求
其他原因(请补充说明)
补充说明:
扫扫下载 App当前访客身份:游客 [
职业JAVA BS系统 架构 业余嵌入式爱好者
:博主,求个文档,邮箱:。非常感...
:求文档,,十分感谢!...
:求文档,sha.qi.,十分感谢!...
:顶一个,我要去
:不错!!!
:不错,顶一个!!!
:不错,顶一个!! @haha
:不错,顶一个!! @haha
:引用来自“叶秀兰”的评论可以发活动到太原城市圈...
:可以发活动到太原城市圈?
今日访问:7
昨日访问:9
本周访问:16
本月访问:138
所有访问:9693
ElasticSearch文档
发表于2年前( 12:04)&&
阅读(3648)&|&评论()
0人收藏此文章,
全中文翻译没那么多时间,这里列个内容索引,便于有目的的查询。
1 Reference
Installation 讲述安装
Configuration 配置文件和群集配置方式
Directory Layout 安装后的目录结构
1.2 Glossary of terms 文本使用的一些术语。
analysis 分析
document 文档,对应于sql中就是一条记录
field 字段
index 索引,相当于库
mapping 映射相当于表结构
node 节点群集相关
primary shard 主分片,相当于表空间,一旦确定不能变更。
replica shard 分片副本
routing 路由,指示document存储到哪个shard上面
shard 分片
source field 源字段,document存储在这个key上
term 分词后的关键字
type 类型相当于table
1.3 API 介绍ES的操作接口,接口支持HTTP协议还有其他。
1.3.1 core 增删改查
1.3.1.1 Index 索引一个document(insert)
1.3.1.2 Delete 删除一个document
1.3.1.3 Get 直接获取一个document(select)
1.3.1.4 Multi Get 获取多个document
1.3.1.5 Update 更新document(update)
1.3.1.6 Search 介绍查询接口,查询支持get参数和requestbody 两种方式
Request Body
URI Request
Query 查询
Filter 过滤,和查询类似,**query会影响facet范围,但是filter不会。**
From / Size 分页
Indices / Types 指定index和type
Rescore document的权值
Suggest 返回输入字符串的建议值,这个类似于搜索引擎的suggest功能
1.3.1.6.10
Highlighting 高亮
1.3.1.6.11
Fields 字段
1.3.1.6.12
Script Fields 脚本编程
1.3.1.6.13
Preference 首选项
1.3.1.6.14
Facets 统计面
1.3.1.6.15
Named Filters 可以对过滤器设置名字
1.3.1.6.16
Search Type 查询的类型
1.3.1.6.17
Index Boost 指示查询优化的参数
1.3.1.6.18
Scroll 卷动,类似于游标的概念,用于大记录集的管理。
1.3.1.6.19
Explain 解释一个查询
1.3.1.6.20
Version document的版本
1.3.1.6.21
document的最低分数。
1.3.1.7 Multi Search 跨索引检索
1.3.1.8 Percolate 预匹配器,类似于订阅的概念,可以检查一个文档符合哪些订阅条件。
1.3.1.9 Bulk 批量接口
1.3.1.10 Bulk UDP UDP协议下的批量接口
1.3.1.11 Count 计数,只返回计数结构而不返回具体列表
1.3.1.12 Delete By Query 删除
1.3.1.13 More Like This 返回相似的结构。
1.3.1.14 Validate 验证一个查询语法,用于开发。
1.3.1.15 Explain 查询解释。
1.3.2 indices 指令(下面的列表都是命令相关的,相当于数据库里的DDL)
1.3.2.1 Aliases 别名,
1.3.2.2 Analyze 查询分析
1.3.2.3 Create Index 创建索引(schema)
1.3.2.4 Delete Index 删除索引
1.3.2.5 Open/Close Index 打开关闭
1.3.2.6 Get Settings
1.3.2.7 Get Mapping 设置类型映射
1.3.2.8 Put Mapping
1.3.2.9 Delete Mapping
Snapshot 只在gateway模式下可用。
Update Settings
Templates 预先设置的mapping模板。当type符合条件的时候应用。
Warmers 查询预热,提高速度
Stats 关于index的统计资料
Status 关于系统的状态信息
Segments 段,Lucene里面的文件
Clear Cache
Indices Exists 索引是否存在
Types Exists 检查type存在
1.3.3 cluster 群集相关的状态查询、指令操作。
1.3.3.1 Health
1.3.3.2 State
1.3.3.3 Update Settings
1.3.3.4 Nodes Info
1.3.3.5 Nodes Stats
1.3.3.6 Nodes Shutdown
1.3.3.7 Nodes Hot Threads
1.3.3.8 Cluster reroute
1.4 Query DSL 这里详细介绍了search的时候可以使用的语法,query和filter类似,看一半就对另一半熟悉了。
queries 介绍query的时候可以使用的语法。
1.4.1.1 match
1.4.1.2 multi_match
1.4.1.3 bool
1.4.1.4 boosting
1.4.1.5 ids
1.4.1.6 custom_score
1.4.1.7 custom_boost_factor
1.4.1.8 constant_score
1.4.1.9 dis_max
has_parent
query_string
span_first
span_multi
top_children
custom_filters_score
1.4.2 filters 介绍过滤使用的语法
1.4.2.1 and
1.4.2.2 bool
1.4.2.3 exists
1.4.2.4 ids
1.4.2.5 limit
1.4.2.6 type
1.4.2.7 geo_bbox
1.4.2.8 geo_distance
1.4.2.9 geo_distance_range
geo_polygon
has_parent
numeric_range
1.5 Mapping 详细介绍内置数据字段和数据类型
1.5.1.1 _uid id和type的结合
1.5.1.2 _id
1.5.1.3 _type
1.5.1.4 _source
1.5.1.5 _all
1.5.1.6 _analyzer
1.5.1.7 _boost
1.5.1.8 _parent
1.5.1.9 _routing
_timestamp document的时间字段,默认是添加的时候的时间,可以映射的某个字
_ttl 生存时间过期doc会自动删除。
types 这里介绍所有支持的数据类型
1.5.2.1 core 基本类型string long int date,
日期支持unix timestamp,和ISO标准的字符串解析(eg T14:28:45.000+08:00)。
在自动生成mapping的时候可以把iso日期字符串映射成date类型,如果是unix timestamp则映射成long。注意,如果你提交的字符串没有时区,ES会认为这个时间是GTM0的时间,做统计的时候就是多了8个小时
在系统内部日期是使用unix long来存储的。
1.5.2.2 array 数组型
1.5.2.3 object 对象
1.5.2.4 root object
1.5.2.5 nested
1.5.2.6 multi_field
1.5.2.7 ip 支持ipv4 to int
1.5.2.8 geo_point 支持地理数据索引
1.5.2.9 geo_shape
attachment 附件,通过插件支持,并且还能索引附件元信息。
1.5.3.1 Meta
1.5.3.2 Node Config node级别的mapping配置。
1.6 Modules 这里介绍ES的组成模块。
Discovery 群集相关
Gateway 群集相关
HTTP httpapi
Transport 群集相关
Network 网络设置
Indices 索引模块
Cluster 群集相关
Scripting 支持的脚本字段。
Thread Pool 线程池设置
介绍插件体系和一个插件列表。
memcached 接口api
Thrift 接口api
1.7 Index Modules 介绍索引模块这个和lucene对应
1.7.1.1 analyzers
Whitespace
1.7.1.2 tokenizers
Edge NGram
Whitespace
UAX URL Email
1.7.1.2.10
Path Hierarchy
1.7.1.3 token filter
ASCII Folding
Edge NGram
Porter Stem
1.7.1.3.10
Word Delimiter
1.7.1.3.11
1.7.1.3.12
Stemmer Override
1.7.1.3.13
Keyword Marker
1.7.1.3.14
Keyword Repeat
1.7.1.3.15
1.7.1.3.16
1.7.1.3.17
1.7.1.3.18
1.7.1.3.19
Compound Word
1.7.1.3.20
1.7.1.3.21
1.7.1.3.22
1.7.1.3.23
1.7.1.3.24
Pattern Replace
1.7.1.3.25
1.7.1.3.26
1.7.1.3.27
1.7.1.4 char filter
HTML Strip
1.7.1.5 plugin
Shard Allocation
Field data
Similarity
1.8 River 河,数据推拉插件可以从别的地方直接拉去数据。
1.9 Java API 介绍官方的java api
1.9.9.1 Queries
1.9.9.2 Filters
2 Clients & Integrations 介绍第三方lib
2.1 Groovy API groovy 的api
2.2 Client 介绍java 库的接口
2.3 Community supported 第三方的制作lib和ui界面以及管理用的插件。
更多开发者职位上
1)">1)">1" ng-class="{current:{{currentPage==page}}}" ng-repeat="page in pages"><li class='page' ng-if="(endIndex<li class='page next' ng-if="(currentPage
相关文章阅读用java实现从文本文件批量导入数据至数据库
- dodomail - ITeye技术网站
今天同事让我准备一个项目的测试数据,要向一个表中插入上千条记录,并且保证每条记录内容不同,如果用手工一条一条插入肯定是不可能,也不会有哪个SB去做这样的事,我最开始想到了用循环,但要求插入的记录内容不能相同,用循环实现比较麻烦,于是我想到了将记录从文本文件导入至数据库(其实SQLServer可利用sql语句实现导入xls或txt文件,在这就不具体说明了),写个简单的具有解析文本文件并将解析结果插入数据库的类,实现批量插入记录的功能。
1、将数据按一定规律录入到一个文本文件,每一行代表一条记录。
下面是数据库建表SQL:
CREATE TABLE t_FltPsgInfo& -- 航班乘客信息
&&& FltNum& VARCHAR(10), -- 航班号
&&& FltLine& VARCHAR(30),& -- 航线
&&& FltDate& VARCHAR(10),& -- 日期
&&& PsgName& VARCHAR(30),& -- 姓名
&&& PsgType& VARCHAR(30), -- 乘客类型,数字表示,目前是1-13
&&& PsgSex& VARCHAR(1),& -- 0 男& 1 女
&&& PsgCab& VARCHAR(1),& -- 几等舱, F/Y& 舱位按字母顺序排列
&&& PsgSeatNo& VARCHAR(5),-- 座位号 2A,22F,根据这个得到一排有多少个座位,共有多少排座位信息
&&& PsgInfo& VARCHAR(2048) -- 详细信息,可能很长
我们将向表t_FltPsgInfo中插入1000条记录。
新建一个文本文件,每一行代表一条记录,如:
HU7804,广州-北京,,谢丽珍,3,1,C,3A,服务保障信息:未用餐随行人员…
其中以“,”作为字段的分隔标志,我们在解析这个文本文件时将根据“,”来拆分字段值。
按照上面的格式,将要插入的数据输入到文本文件中,注意,是每一行代表一条记录,或者你已有从数据库导出的文本文件,那你就只需找到文件的规律,稍作调整就行了。
2、编写Java源码
1》数据库操作类InsertDB.java
import java.sql.C
import java.sql.DriverM
import java.sql.ResultS
import java.sql.S
public class InsertDB {
private static final String user = "sa";
private static final String pwd = "sa";
private static final String url = "jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=hhfly";
private static final String driver = "com.microsoft.jdbc.sqlserver.SQLServerDriver";
public static Connection getCon() {
Connection con =
Class.forName(driver).newInstance();
con = DriverManager.getConnection(url, user, pwd);
if (con != null) {
System.out.println("你已连接到数据库:" + con.getCatalog());
} catch (Exception e) {
System.out.println("连接数据库失败!");
e.printStackTrace();
public boolean insertDB(String FltNum, String FltLine, String FltDate,
String PsgName, String PsgType, String PsgSex, String PsgCab,
String PsgSeatNo, String PsgInfo) {
Connection con =
Statement stm =
boolean flag =
String sql = "insert into t_FltPsgInfo values('" + FltNum + "','"
+ FltLine + "','" + FltDate + "','" + PsgName + "','" + PsgType
+ "','" + PsgSex + "','" + PsgCab + "','" + PsgSeatNo + "','"
+ PsgInfo + "')";
con = getCon();
stm = con.createStatement();
int i = stm.executeUpdate(sql);
if (i & 0) {
System.out.println(flag + "插入数据成功!");
} catch (Exception e) {
e.printStackTrace();
} finally {
close(null, stm, con);
//关闭相关连接
public void close(ResultSet rs, Statement stm, Connection con) {
if (rs != null)
rs.close();
} catch (Exception e) {
e.printStackTrace();
if (stm != null)
stm.close();
} catch (Exception e) {
e.printStackTrace();
if (con != null)
con.close();
} catch (Exception e) {
e.printStackTrace();
2》数据采集类DataGather.java
import java.io.RandomAccessF
import java.io.UnsupportedEncodingE
public class DataGather {
private static final String path = "src/resource/test";
public static final String openFileStyle = "r";
public static final String fieldLimitChar = ",";
public static final int fieldAllCount = 9;
private String FltN
private String FltL
private String FltD
private String PsgN
private String PsgT
private String PsgS
private String PsgC
private String PsgSeatNo;
private String PsgI
* 功能:解析文本文件
public void loadFile() {
RandomAccessFile raf = new RandomAccessFile(path, openFileStyle);
String line_record = raf.readLine();
while (line_record != null) {
// 解析每一条记录
parseRecord(line_record);
line_record = raf.readLine();
System.out.println("共有合法的记录" + count + "条");
} catch (Exception e) {
e.printStackTrace();
* 功能:具体解析每一条记录,这里可以增加很多对记录的解析判断条件,如是否为字母、
* 数字、email等。
private void parseRecord(String line_record) throws Exception {
//拆分记录
String[] fields = line_record.split(fieldLimitChar);
if (fields.length == fieldAllCount) {
FltNum = tranStr(fields[0]);
FltLine = tranStr(fields[1]);
FltDate = tranStr(fields[2]);
PsgName = tranStr(fields[3]);
PsgType = tranStr(fields[4]);
PsgSex = tranStr(fields[5]);
PsgCab = tranStr(fields[6]);
PsgSeatNo = tranStr(fields[7]);
PsgInfo = tranStr(fields[8]);
System.out.println(FltNum + " " + FltLine + " " + FltDate + " "
+ PsgName + " " + PsgType + " " + PsgSex + " " + PsgCab
+ " " + PsgSeatNo + " " + PsgInfo);
InsertDB db = new InsertDB();
db.insertDB(FltNum, FltLine, FltDate, PsgName, PsgType, PsgSex,
PsgCab, PsgSeatNo, PsgInfo);
private String tranStr(String oldstr) {
String newstr = "";
newstr = new String(oldstr.getBytes("ISO-8859-1"), "GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
3》测试类Test.java
public class Test {
public static void main(String[] args) {
DataGather gather = new DataGather ();
gather.loadFile();
} catch (Exception e) {
e.printStackTrace();
运行测试类,得到结果:
向数据库插入数据成功!
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jojoy_828/archive//1911236.aspx
浏览: 461518 次
来自: 北京
你的这个SQL有问题的
dddddddddddddd
人的贪婪无止境,只能控制,不能满足

我要回帖

更多关于 批量导入sql文本 空格 的文章

 

随机推荐