zoukankan      html  css  js  c++  java
  • 文档操作

    • 文档元数据
    一个文档不只有数据。它还包含了元数据(metadata)——关于文档的信息。
    _index:文档存储的地方,必须是全部小写,不能以下划线开头,不能包含逗号。
    _type:文档代表的对象的类,可以是大写或小写,不能包含下划线或逗号。
    _id:文档的唯一标识,可以自定义 _id  ,也可以让Elasticsearch帮你自动生成
    
    
    • 索引一个文档
    文档通过其 _index  、 _type  、 _id  唯一确定。
    新版版中使用如下三种:
    /{index}/_doc/{id}
    /{index}/_doc
    /{index}/_create/{id}
    
    # 自定义id
    类型:
    PUT /{index}/{type}/{id}
    {
    "field": "value",
    ...
    }
    
    
    PUT /website/blog/123
    {
    "title": "My first blog entry",
    "text": "Just trying this out...",
    "date": "2014/01/01"
    }
    
    # 相应
    #! Deprecation: [types removal] Specifying types in document index requests is deprecated, use the typeless endpoints instead (/{index}/_doc/{id}, /{index}/_doc, or /{index}/_create/{id}).
    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "123",
      "_version" : 1,
      "result" : "created",
      "_shards" : {
        "total" : 2,
        "successful" : 2,
        "failed" : 0
      },
      "_seq_no" : 0,
      "_primary_term" : 1
    }
    
    新元素: _version 。Elasticsearch中每个文档都有版本号,每当文档变化(包括删除)都会使 _version  增加
    
    # 自增id
    请求结构发生了变化: PUT  方法—— “在这个URL中存储文档”  变成了 POST  方法—— "在这个类型下存储文档"  。
    (译者注:原来是把文档存储到某个ID对应的空间,现在是把这个文档添加到某个 _type  下)。
    
    POST /website/blog/
    {
    "title": "My second blog entry",
    "text": "Still trying this out...",
    "date": "2014/01/01"
    }
    
    #! Deprecation: [types removal] Specifying types in document index requests is deprecated, use the typeless endpoints instead (/{index}/_doc/{id}, /{index}/_doc, or /{index}/_create/{id}).
    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "CLlv9W4BMI_HpWYyWHR5",
      "_version" : 1,
      "result" : "created",
      "_shards" : {
        "total" : 2,
        "successful" : 2,
        "failed" : 0
      },
      "_seq_no" : 1,
      "_primary_term" : 1
    }
    
    说明:自动生成的ID有22个字符长,URL-safe, Base64-encoded string universally unique identifiers, 或者叫 UUIDs。
    
    • 检索文档
    GET /website/blog/123?pretty
    
    #! Deprecation: [types removal] Specifying types in document get requests is deprecated, use the /{index}/_doc/{id} endpoint instead.
    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "123",
      "_version" : 1,
      "_seq_no" : 0,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "title" : "My first blog entry",
        "text" : "Just trying this out...",
        "date" : "2014/01/01"
      }
    }
    
    
    响应包含了现在熟悉的元数据节点,增加了 _source  字段,它包含了在创建索引时我们发送给Elasticsearch的原始文档。
    
    在任意的查询字符串中增加 pretty  参数,会让Elasticsearch美化输出(pretty-print)JSON响应以便更加容易阅读。 _source  字段不会被美化,它的样子与输入的一致。
    
    GET请求返回的响应内容包括 {"found": true}  。这意味着文档已经找到。如果我们请求一个不存在的文档,依旧会得到一个JSON,不过 found  值变成了 false  。
    
    此外,HTTP响应状态码也会变成 '404 Not Found'  代替 '200 OK'  .
    
    • 检索文档的一部分
    通常, GET 请求将返回文档的全部,存储在 _source  参数中.请求个别字段可以使用 _source  参数。多个字段可以使用逗号分隔:
    GET /website/blog/123?_source=title,text
    
    只想得到 _source  字段而不要其他的元数据:
    GET /website/blog/123/_source
    
    
    • 检索文档是否存在
    # HEAD  请求不会返回响应体,只有HTTP头
    curl -XHEAD "http://192.168.75.21:9200/website/blog/1234"
    
    HEAD /website/blog/123
    
    存在返回:200 - OK
    不存在返回:404 - Not Found
    
    • 更新整个文档
    文档在Elasticsearch中是不可变的,如果需要更新已存在的文档,可以使用 index  API 重建索引(reindex) 或者替换掉它
    PUT /website/blog/123
    {
      "title": "My first blog entry",
      "text": "I am starting to get the hang of this...",
      "date": "2014/01/02"
    }
    
    在响应中,可以看到Elasticsearch把 _version  增加了
    #! Deprecation: [types removal] Specifying types in document index requests is deprecated, use the typeless endpoints instead (/{index}/_doc/{id}, /{index}/_doc, or /{index}/_create/{id}).
    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "123",
      "_version" : 2,
      "result" : "updated",
      "_shards" : {
        "total" : 2,
        "successful" : 2,
        "failed" : 0
      },
      "_seq_no" : 2,
      "_primary_term" : 1
    }
    
    在内部,Elasticsearch已经标记旧文档为删除并添加了一个完整的新文档。旧版本文档不会立即消失,但也不能去访问它。Elasticsearch会在继续索引更多数据时清理被删除的文档。
    
    
    • 创建一个新文档
    当索引一个文档,我们如何确定是完全创建了一个新的还是覆盖了一个已经存在的呢?
    请记住 _index  、 _type  、 _id  三者唯一确定一个文档。所以要想保证文档是新加入的,最简单的方式是使用 POST  方法让Elasticsearch自动生成唯一 _id  :
    POST /website/blog/
    { ... }
    
    如果想使用自定义的 _id  ,我们必须告诉Elasticsearch应该在 _index  、 _type  、 _id  三者都不同时才接受请求。为了做到这点有两种方法:
    第一种方法使用 op_type  查询参数:
    PUT /website/blog/123?op_type=create
    { ... }
    
    或者第二种方法是在URL后加 /_create  做为端点:
    PUT /website/blog/123/_create
    { ... }
    
    如果请求成功的创建了一个新文档,Elasticsearch将返回正常的元数据且响应状态是 Created  。
    #! Deprecation: [types removal] Specifying types in document index requests is deprecated, use the typeless endpoints instead (/{index}/_doc/{id}, /{index}/_doc, or /{index}/_create/{id}).
    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "124",
      "_version" : 1,
      "result" : "created",
      "_shards" : {
        "total" : 2,
        "successful" : 2,
        "failed" : 0
      },
      "_seq_no" : 3,
      "_primary_term" : 1
    }
    
    
    另一方面,如果包含相同的 _index  、 _type  和 _id  的文档已经存在,Elasticsearch将返回 409 Conflict  响应状态码
    {
      "error": {
        "root_cause": [
          {
            "type": "version_conflict_engine_exception",
            "reason": "[123]: version conflict, document already exists (current version [2])",
            "index_uuid": "AUKIFVfaRh2WekJColRQHA",
            "shard": "0",
            "index": "website"
          }
        ],
        "type": "version_conflict_engine_exception",
        "reason": "[123]: version conflict, document already exists (current version [2])",
        "index_uuid": "AUKIFVfaRh2WekJColRQHA",
        "shard": "0",
        "index": "website"
      },
      "status": 409
    }
    
    
    • 删除文档
    删除文档使用 DELETE  方法:
    DELETE /website/blog/123
    
    如果文档被找到,Elasticsearch将返回 deleted  状态和以下响应体。注意 _version  数字已经增加了。
    #! Deprecation: [types removal] Specifying types in document index requests is deprecated, use the /{index}/_doc/{id} endpoint instead.
    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "123",
      "_version" : 3,
      "result" : "deleted",
      "_shards" : {
        "total" : 2,
        "successful" : 2,
        "failed" : 0
      },
      "_seq_no" : 5,
      "_primary_term" : 1
    }
    如果文档未找到,我们将得到一个 404 Not Found  状态码
    DELETE /website/blog/123
    
    #! Deprecation: [types removal] Specifying types in document index requests is deprecated, use the /{index}/_doc/{id} endpoint instead.
    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "123",
      "_version" : 2,
      "result" : "not_found",
      "_shards" : {
        "total" : 2,
        "successful" : 2,
        "failed" : 0
      },
      "_seq_no" : 8,
      "_primary_term" : 1
    }
    尽管文档不存在—— "not_found"  但是 _version  依旧增加了。这是内部记录的一部分,它确保在多节点间不同操作可以有正确的顺序。
    删除一个文档也不会立即从磁盘上移除,它只是被标记成已删除。Elasticsearch将会在你之后添加更多索引的时候才会在后台进行删除内容的清理。
    
    • 处理冲突
    当使用 index  API更新文档的时候,我们读取原始文档,做修改,然后将整个文档(whole document)一次性重新索引。最近的索引请求会生效——Elasticsearch中只存储最后被索引的任何文档。如果其他人同时也修改了这个文档,他们的修改将会丢失。
    
    变化越是频繁,或读取和更新间的时间越长,越容易丢失我们的更改。在数据库中,有两种通用的方法确保在并发更新时修改不丢失:
    
    悲观并发控制(Pessimistic concurrency control)
    这在关系型数据库中被广泛的使用,假设冲突的更改经常发生,为了解决冲突我们把访问区块化。典型的例子是在读一行数据前锁定这行,然后确保只有加锁的那个线程可以修改这行数据。
    
    乐观并发控制(Optimistic concurrency control):
    被Elasticsearch使用,假设冲突不经常发生,也不区块化访问,然而,如果在读写过程中数据发生了变化,更新操作将失败。这时候由程序决定在失败后如何解决冲突。实际情况中,可以重新尝试更新,刷新数据(重新读取)或者直接反馈给用户。
    
    Elasticsearch是分布式的。当文档被创建、更新或删除,文档的新版本会被复制到集群的其它节点。Elasticsearch即是同步的又是异步的,意思是这些复制请求都是平行发送的,并无序(out of sequence)的到达目的地。这就需要一种方法确保老版本的文档永远不会覆盖新的版本。
    
    Elasticsearch使用这个 _version  保证所有修改都被正确排序。当一个旧版本出现在新版本之后,它会被简单的忽略。
    
    利用 _version  的这一优点确保数据不会因为修改冲突而丢失。我们可以指定文档的 version  来做想要的更改。如果那个版本号不是现在的,我们的请求就失败了。
    
    PUT /website/blog/1/_create
    {
      "title": "My first blog entry",
      "text": "Just trying this out..."
    }
    
    #! Deprecation: [types removal] Specifying types in document index requests is deprecated, use the typeless endpoints instead (/{index}/_doc/{id}, /{index}/_doc, or /{index}/_create/{id}).
    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "1",
      "_version" : 1,
      "result" : "created",
      "_shards" : {
        "total" : 2,
        "successful" : 2,
        "failed" : 0
      },
      "_seq_no" : 9,
      "_primary_term" : 1
    }
    
    响应体告诉我们这是一个新建的文档,它的 _version  是 1  。现在假设我们要编辑这个文档:把数据加载到web表单中,修改,然后保存成新版本。
    
    首先我们检索文档:
    GET /website/blog/1
    
    响应体包含相同的 _version  是 1
    
    现在,当我们通过重新索引文档保存修改时,我们这样指定了 version  参数:
    PUT /website/blog/1?version=1
    
    严重注意,说明:使用内部版本这个没有走通,估计是文档中版本太低的缘故!!!!!!!!
    
    
    • 使用外部版本控制系统
    在Elasticsearch的查询字符串后面添加 version_type=external  来使用。版本号必须是整数,大于零小于 9.2e+18  ——Java中的正的 long  。
    
    外部版本号与之前说的内部版本号在处理的时候有些不同。它不再检查 _version  是否与请求中指定的一致,而是检查是否小于指定的版本。如果请求成功,外部版本号就会被存储到 _version  中。
    
    外部版本号不仅在索引和删除请求中指定,也可以在创建(create)新文档中指定。
    
    创建一个包含外部版本号 5  的新博客
    PUT /website/blog/1?version=5&version_type=external
    {
      "title": "My first blog entry",
      "text": "Starting to get the hang of this...111111"
    }
    
    在响应中,我们能看到当前的 _version  号码是 5  :
    #! Deprecation: [types removal] Specifying types in document index requests is deprecated, use the typeless endpoints instead (/{index}/_doc/{id}, /{index}/_doc, or /{index}/_create/{id}).
    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "1",
      "_version" : 5,
      "result" : "updated",
      "_shards" : {
        "total" : 2,
        "successful" : 2,
        "failed" : 0
      },
      "_seq_no" : 13,
      "_primary_term" : 1
    }
    
    如果重新运行这个请求,就会返回一个像之前一样的冲突错误,因为指定的外部版本号不大于当前在Elasticsearch中的版本。
    
    
    • 文档局部更新
    最简单的 update  请求表单接受一个局部文档参数 doc  ,它会合并到现有文档中——对象合并在一起,存在的标量字段被覆盖,新字段被添加。
    
    GET /website/blog/1
    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "1",
      "_version" : 5,
      "_seq_no" : 13,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "title" : "My first blog entry",
        "text" : "Starting to get the hang of this...111111"
      }
    }
    
    POST /website/blog/1/_update
    {
      "doc": {
        "tags": [
          "testing"
        ],
        "views": 0
      }
    }
    
    返回结果
    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "1",
      "_version" : 6,
      "result" : "updated",
      "_shards" : {
        "total" : 2,
        "successful" : 2,
        "failed" : 0
      },
      "_seq_no" : 14,
      "_primary_term" : 1
    }
    
    再次查看,新添加的字段已经被添加到 _source  字段中
    GET /website/blog/1
    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "1",
      "_version" : 6,
      "_seq_no" : 14,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "title" : "My first blog entry",
        "text" : "Starting to get the hang of this...111111",
        "views" : 0,
        "tags" : [
          "testing"
        ]
      }
    }
    
    
    • 使用脚本局部更新
    脚本支持非常多的API,例如搜索、排序、聚合和文档更新。脚本可以通过请求的一部分、检索特殊的 .scripts  索引或者从磁盘加载方式执行。
    
    默认的脚本语言是Groovy,一个快速且功能丰富的脚本语言,语法类似于Javascript。它在一个沙盒(sandbox)中运行,以防止恶意用户毁坏Elasticsearch或攻击服务器。
    
    脚本能够使用 update  API改变 _source  字段的内容,它在脚本内部以 ctx._source  表示
    使用脚本增加博客的 views  数量
    POST /website/blog/1/_update
    {
      "script": "ctx._source.views+=1"
    }
    响应结果
    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "1",
      "_version" : 7,
      "result" : "updated",
      "_shards" : {
        "total" : 2,
        "successful" : 2,
        "failed" : 0
      },
      "_seq_no" : 15,
      "_primary_term" : 1
    }
    
    还可以使用脚本增加一个新标签到 tags  数组中。定义了一个新标签做为参数而不是硬编码在脚本里。这允许Elasticsearch未来可以重复利用脚本,而不是在想要增加新标签时必须每次编译新脚本:
    
    注意,说明:这个没有走通!!!!!
    
    • 更新可能不存在的文档
    使用 upsert  参数定义文档来使其不存在时被创建
    POST /website/pageviews/1/_update
    {
      "script": "ctx._source.views+=1",
      "upsert": {
        "views": 1
      }
    }
    
    注意,说明:这个无法走通,因为在新版本中一个索引只能有一个type,不能有多个!!!!!!!!!!!
    
    
    • 更新和冲突
    为了避免丢失数据, update  API在检索(retrieve)阶段检索文档的当前 _version  ,然后在重建索引(reindex)阶段通过 index  请求提交。如果其他进程在检索(retrieve)和重建索引(reindex)阶段修改了文档, _version  将不能被匹配,然后更新失败。
    
    可以通过 retry_on_conflict  参数设置重试次数来自动完成,这样 update  操作将会在发生错误前重试——这个值默认为0。
    
    POST /web/pageviews/1/_update?retry_on_conflict=5
    {
      "script": "ctx._source.views+=1",
      "upsert": {
        "views": 0
      }
    }
    
    • 检索多个文档
    在一个请求中使用multi-get或者 mget  API
    mget  API参数是一个 docs  数组,数组的每个节点定义一个文档的 _index  、 _type  、 _id  元数据。如果你只想检索一个或几个确定的字段,也可以定义一个 _source  参数:
    POST /_mget
    {
      "docs": [
        {
          "_index": "website",
          "_type": "blog",
          "_id": 1
        },
        {
          "_index": "web",
          "_type": "pageviews",
          "_id": 1,
          "_source": "views"
        }
      ]
    }
    
    {
      "docs" : [
        {
          "_index" : "website",
          "_type" : "blog",
          "_id" : "1",
          "_version" : 7,
          "_seq_no" : 15,
          "_primary_term" : 1,
          "found" : true,
          "_source" : {
            "title" : "My first blog entry",
            "text" : "Starting to get the hang of this...111111",
            "views" : 1,
            "tags" : [
              "testing"
            ]
          }
        },
        {
          "_index" : "web",
          "_type" : "pageviews",
          "_id" : "1",
          "_version" : 2,
          "_seq_no" : 1,
          "_primary_term" : 1,
          "found" : true,
          "_source" : {
            "views" : 2
          }
        }
      ]
    }
    
    响应体也包含一个 docs  数组,每个文档还包含一个响应,它们按照请求定义的顺序排列。每个这样的响应与单独使用 get  request响应体相同
    
    如果所有文档具有相同 _index  和 _type  ,可以通过简单的 ids  数组来代替完整的 docs  数组:
    POST /website/blog/_mget
    {
      "ids": ["2","1"]
    }
    
    不存在的文档会在响应体中被告知
    {
      "docs" : [
        {
          "_index" : "website",
          "_type" : "blog",
          "_id" : "2",
          "found" : false
        },
        {
          "_index" : "website",
          "_type" : "blog",
          "_id" : "1",
          "_version" : 7,
          "_seq_no" : 15,
          "_primary_term" : 1,
          "found" : true,
          "_source" : {
            "title" : "My first blog entry",
            "text" : "Starting to get the hang of this...111111",
            "views" : 1,
            "tags" : [
              "testing"
            ]
          }
        }
      ]
    }
    
    不存在的文档并不影响其他文档的检索。每个文档的检索和报告都是独立的。
    
    尽管有一个文档没有被找到,但HTTP请求状态码还是 200  。事实上,就算所有文档都找不到,请求也还是返回 200  ,原因是 mget  请求本身成功了。如果想知道每个文档是否都成功了,需要检查 found 标志。
    
    
    • 批量操作
    bulk  API允许使用单一请求来实现多个文档的 create  、 index  、 update  或 delete  。这对索引类似于日志活动这样的数据流非常有用,它们可以以成百上千的数据为一个批次按序进行索引。
    
    bulk  请求体如下,它有一点不同寻常:
    { action: { metadata }}
    
    { request body }
    
    { action: { metadata }}
    
    { request body }
    
    
    这种格式类似于用 "
    "  符号连接起来的一行一行的JSON文档流(stream)。两个重要的点需要注意:
        - 每行必须以 "
    "  符号结尾,包括最后一行。这些都是作为每行有效的分离而做的标记
        - 每一行的数据不能包含未被转义的换行符,它们会干扰分析——这意味着JSON不能被美化打印。
    
    action/metadata这一行定义了文档行为(what action)发生在哪个文档(which document)之上。
    
    行为(action)必须是以下几种:
        create:当文档不存在时创建之
        index:创建新文档或替换已有文档
        update:局部更新文档
        delete:删除一个文档
    
    在索引、创建、更新或删除时必须指定文档的 _index  、 _type  、 _id  这些元数据 (metadata)。
    
    删除请求:{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }}
    
    请求体(request body)由文档的 _source  组成——文档所包含的一些字段以及其值。
    删除操作不需要请求体(request body)
    
    如果没有定义 _id  ,ID将会被自动创建
    PUT /_bulk
    {"index":{"_index":"website","_type":"_doc"}}
    {"title":"My second blog post"}
    
    bulk  请求表单
    POST /_bulk
    { "delete": { "_index": "website", "_type": "_doc", "_id": "1234" }} # 删除操作不需要请求体(request body)
    { "create": { "_index": "website", "_type": "_doc", "_id": "123" }}
    { "title": "My first _doc post" }
    { "index": { "_index": "website", "_type": "_doc" }}
    { "title": "My second _doc post" }
    { "update": { "_index": "website", "_type": "_doc", "_id": "123", "retry_on_conflict" :5}}
    { "doc" : {"title" : "My updated _doc post"} }
    
    Elasticsearch响应包含一个 items  数组,它罗列了每一个请求的结果,结果的顺序与请求的顺序相同:
    #! Deprecation: [types removal] Specifying types in bulk requests is deprecated.
    {
      "took" : 18,
      "errors" : true,
      "items" : [
        {
          "delete" : {
            "_index" : "website",
            "_type" : "_doc",
            "_id" : "1234",
            "_version" : 1,
            "result" : "not_found",
            "_shards" : {
              "total" : 2,
              "successful" : 2,
              "failed" : 0
            },
            "_seq_no" : 38,
            "_primary_term" : 1,
            "status" : 404
          }
        },
        {
          "create" : {
            "_index" : "website",
            "_type" : "_doc",
            "_id" : "123",
            "status" : 409,
            "error" : {
              "type" : "version_conflict_engine_exception",
              "reason" : "[123]: version conflict, document already exists (current version [15])",
              "index_uuid" : "AUKIFVfaRh2WekJColRQHA",
              "shard" : "0",
              "index" : "website"
            }
          }
        },
        {
          "index" : {
            "_index" : "website",
            "_type" : "_doc",
            "_id" : "r7nZ9W4BMI_HpWYyr3eX",
            "_version" : 1,
            "result" : "created",
            "_shards" : {
              "total" : 2,
              "successful" : 2,
              "failed" : 0
            },
            "_seq_no" : 39,
            "_primary_term" : 1,
            "status" : 201
          }
        },
        {
          "update" : {
            "_index" : "website",
            "_type" : "_doc",
            "_id" : "123",
            "_version" : 15,
            "result" : "noop",
            "_shards" : {
              "total" : 2,
              "successful" : 2,
              "failed" : 0
            },
            "status" : 200
          }
        }
      ]
    }
    
    
    每个子请求都被独立的执行,所以一个子请求的错误并不影响其它请求。如果任何一个请求失败,顶层的 error  标记将被设置为 true  ,然后错误的细节将在相应的请求中被报告
    这些说明 bulk  请求不是原子操作——它们不能实现事务。每个请求操作时分开的,所以每个请求的成功与否不干扰其它操作。
    
    
    - 不要重复
    可能在同一个 index  下的同一个 type  里批量索引日志数据
    就像 mget  API, bulk  请求也可以在URL中使用 /_index  或 /_index/_type
    POST /website/_bulk
    { "index": { "_type": "log" }}
    { "event": "User logged in" }
    
    可以覆盖元数据行的 _index  和 _type  ,在没有覆盖时它会使用URL中的值作为默认值:
    POST /website/log/_bulk
    { "index": {}}
    { "event": "User logged in" }
    { "index": { "_type": "blog" }}
    { "title": "Overriding the default type" }
    
    - 多大才算太大?
    整个批量请求需要被加载到接受我们请求节点的内存里,所以请求越大,给其它请求可用的内存就越小。有一个最佳的 bulk  请求大小。超过这个大小,性能不再提升而且可能降低。
    
    这个最佳点(sweetspot)还是容易找到的:
    试着批量索引标准的文档,随着大小的增长,当性能开始降低,说明你每个批次的大小太大了。开始的数量可以在1000~5000个文档之间,如果你的文档非常大,可以使用较小的批次。
    通常着眼于你请求批次的物理大小是非常有用的。一千个1kB的文档和一千个1MB的文档大不相同。一个好的批次最好保持在5-15MB大小间。
    
    
  • 相关阅读:
    Java学习 · 初识 多线程
    Java学习 · 初识 IO流
    Java学习 · 初识 容器和数据结构
    Java学习 · 初识 异常机制
    Java学习 · 初识 面向对象深入二
    纯golang爬虫实战-(六)-关于cookiejar的理解 (2020-02-14 13:50)
    纯golang爬虫实战-(五)-登录并带cookie访问
    golang使用gopacket包进行数据包捕获实践(未成功)
    纯go+sqlite3+html/template网站(类似MVC实现数据库CURD、上传下载文件)-最少依赖才是硬道理
    纯golang+sqlite3 CRUD
  • 原文地址:https://www.cnblogs.com/sanduzxcvbnm/p/12029317.html
Copyright © 2011-2022 走看看