精华内容
下载资源
问答
  • 索引是创建在表上的,对数据库表中一列或列的值进行排序的一种结构其作用主要在于提高查询的速度,降低数据库系统的性能开销通过索引,查询数据不必读完记录的全部信息进行匹配,而是只查询索引索引相当于字典中...

    索引是创建在表上的,对数据库表中一列或多列的值进行排序的一种结构

    其作用主要在于提高查询的速度,降低数据库系统的性能开销

    通过索引,查询数据不必读完记录的全部信息进行匹配,而是只查询索引列

    索引相当于字典中的音序表,要查询某字时可以在音序表中找到

    然后直接跳转到那一音序所在位置,而不必从字典第一页开始翻,逐字匹配

    tips:索引虽能提高查询速度,但在插入记录时会按照索引进行排序,因此降低了插入速度

    最好的操作方式是先删除索引,插入大量记录后再创建索引

    索引分类

    1.普通索引:不附加任何限制条件,可创建在任何数据类型中

    2.唯一性索引:使用unique参数可以设置索引为唯一性索引,在创建索引时,限制该索引的值必须唯一,主键就是一种唯一性索引

    3.全文索引:使用fulltext参数可以设置索引为全文索引。全文索引只能创建在char、varchar或text类型的字段上。查询数据量较大的字符串类型字段时,效果明显。但只有MyISAM存储引擎支持全文检索

    4.单列索引:在表中单个字段上创建的索引,单列索引可以是任何类型,只要保证索引只对应一个一个字段

    5.多列索引:在表中多个字段上创建的索引,该索引指向创建时对应的多个字段

    6.空间索引:使用spatial参数可以设置索引为空间索引,空间索引只能建立在空间数据类型上比如geometry,并且不能为空,目前只有MyISAM存储引擎支持

    在创建表时创建索引

    创建普通索引

    mysql> create table index1(

    -> id int,

    -> name varchar(20),

    -> sex boolean,

    -> index(id)

    -> );

    Query OK, 0 rows affected (0.11 sec)

    此处在id字段上创建索引,show create table可查看

    创建唯一性索引

    mysql> create table index2(

    -> id int unique,

    -> name varchar(20),

    -> unique index index2_id(id ASC)

    -> );

    Query OK, 0 rows affected (0.12 sec)

    此处使用id字段创建了一个名为index2_id的索引

    这里的id字段可以不设置唯一性约束,但这样一来索引就没有作用

    创建全文索引

    mysql> create table index3(

    -> id int,

    -> info varchar(20),

    -> fulltext index index3_info(info)

    -> )engine=MyISAM;

    Query OK, 0 rows affected (0.07 sec)

    要注意创建全文索引时只能使用MyISAM存储引擎

    创建单列索引

    mysql> create table index4(

    -> id int,

    -> subject varchar(30),

    -> index index4_st(subject(10))

    -> );

    Query OK, 0 rows affected (0.12 sec)

    此处subject字段长度是30,而索引长度则是10

    这么做的目的在于提高查询速度,对于字符型的数据不用查询全部信息

    创建多列索引

    mysql> create table index5(

    -> id int,

    -> name varchar(20),

    -> sex char(4),

    -> index index5_ns(name,sex)

    -> );

    Query OK, 0 rows affected (0.10 sec)

    可以看出,这里使用了name字段和sex字段创建索引列

    创建空间索引

    mysql> create table index6(

    -> id int,

    -> space geometry not null,

    -> spatial index index6_sp(space)

    -> )engine=MyISAM;

    Query OK, 0 rows affected (0.07 sec)

    这里需要注意空间space字段不能为空,还有存储引擎

    在已经存在的表上创建索引

    创建普通索引

    mysql> create index index7_id on example0(id);

    Query OK, 0 rows affected (0.07 sec)

    Records: 0  Duplicates: 0  Warnings: 0

    这里在现有表的id字段上创建了一条名为index7_id的索引

    创建唯一性索引

    mysql> create unique index index8_id on example1(course_id);

    Query OK, 0 rows affected (0.16 sec)

    Records: 0  Duplicates: 0  Warnings: 0

    此处只需要在index关键字前面加上unique即可

    至于表中的course_id字段,最要也设置唯一性约束条件

    创建全文索引

    mysql> create fulltext index index9_info on example2(info);

    Query OK, 0 rows affected (0.07 sec)

    Records: 0  Duplicates: 0  Warnings: 0

    fulltext关键字用来设置全文引擎,此处的表必须是MyISAM存储引擎

    创建单列索引

    mysql> create index index10_addr on example3(address(4));

    Query OK, 0 rows affected (0.16 sec)

    Records: 0  Duplicates: 0  Warnings: 0

    此表中address字段的长度是20,这里只查询4字节,不需要全部查询

    创建多列索引

    mysql> create index index11_na on example4(name,address);

    Query OK, 0 rows affected (0.16 sec)

    Records: 0  Duplicates: 0  Warnings: 0

    索引创建好之后,查询中必须有name字段才能使用

    创建空间索引

    mysql> create spatial index index12_line on example5(space);

    Query OK, 0 rows affected (0.07 sec)

    Records: 0  Duplicates: 0  Warnings: 0

    这里需要注意存储引擎是MyISAM,还有空间数据类型

    用alter table语句来创建索引

    创建普通索引

    mysql> alter table example6 add index index13_n(name(20));

    Query OK, 0 rows affected (0.16 sec)

    Records: 0  Duplicates: 0  Warnings: 0

    创建唯一性索引

    mysql> alter table example7 add unique index index14_id(id);

    Query OK, 0 rows affected (0.20 sec)

    Records: 0  Duplicates: 0  Warnings:

    创建全文索引

    mysql> alter table example8 add fulltext index index15_info(info);

    Query OK, 0 rows affected (0.08 sec)

    Records: 0  Duplicates: 0  Warnings: 0

    创建单列索引

    mysql> alter table example9 add index index16_addr(address(4));

    Query OK, 0 rows affected (0.16 sec)

    Records: 0  Duplicates: 0  Warnings: 0

    创建多列索引

    mysql> alter table example10 add index index17_in(id,name);

    Query OK, 0 rows affected (0.16 sec)

    Records: 0  Duplicates: 0  Warnings: 0

    创建空间索引

    mysql> alter table example11 add spatial index index18_space(space);

    Query OK, 0 rows affected (0.06 sec)

    Records: 0  Duplicates: 0  Warnings: 0

    到此,三种操作方式,每种索引类别的建立就都列举了

    对于索引,重要的是理解索引的概念,明白索引的种类

    更多的是自己的使用经验

    最后来看看索引的删除

    删除索引

    mysql> drop index index18_space on example11;

    Query OK, 0 rows affected (0.08 sec)

    Records: 0  Duplicates: 0  Warnings: 0

    这里是刚刚创建的一条索引

    其中index18_space是索引名,example11是表名

    mysql索引最左匹配原则的理解

    这是你的表结构,有三个字段,分别是id,name,cid

    CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `cid` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `name_cid_INX` (`name`,`cid`),) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8

    索引方面:id是主键,(name,cid)是一个多列索引。

    -----------------------------------------------------------------------------

    下面是你有疑问的两个查询:

    EXPLAIN SELECT * FROM student WHERE cid=1;

    52787897

    EXPLAIN SELECT * FROM student WHERE cid=1 AND name='小红';

    52787897

    你的疑问是:sql查询用到索引的条件是必须要遵守最左前缀原则,为什么上面两个查询还能用到索引?

    ---------------------------------------------------------------------------------------------------------------------------

    讲上面问题之前,我先补充一些知识,因为我觉得你对索引理解是狭隘的:

    上述你的两个查询的explain结果中显示用到索引的情况类型是不一样的。,可观察explain结果中的type字段。你的查询中分别是:

    1. type: index

    2. type: ref

    解释:

    index:这种类型表示是mysql会对整个该索引进行扫描。要想用到这种类型的索引,对这个索引并无特别要求,只要是索引,或者某个复合索引的一部分,mysql都可能会采用index类型的方式扫描。但是呢,缺点是效率不高,mysql会从索引中的第一个数据一个个的查找到最后一个数据,直到找到符合判断条件的某个索引。

    所以:对于你的第一条语句:

    EXPLAIN SELECT * FROM student WHERE cid=1;

    判断条件是cid=1,而cid是(name,cid)复合索引的一部分,没有问题,可以进行index类型的索引扫描方式。explain显示结果使用到了索引,是index类型的方式。

    ---------------------------------------------------------------------------------------------------------------------------

    ref:这种类型表示mysql会根据特定的算法快速查找到某个符合条件的索引,而不是会对索引中每一个数据都进行一 一的扫描判断,也就是所谓你平常理解的使用索引查询会更快的取出数据。而要想实现这种查找,索引却是有要求的,要实现这种能快速查找的算法,索引就要满足特定的数据结构。简单说,也就是索引字段的数据必须是有序的,才能实现这种类型的查找,才能利用到索引。

    有些了解的人可能会问,索引不都是一个有序排列的数据结构么。不过答案说的还不够完善,那只是针对单个索引,而复合索引的情况有些同学可能就不太了解了。

    下面就说下复合索引:

    以该表的(name,cid)复合索引为例,它内部结构简单说就是下面这样排列的:

    52787897

    mysql创建复合索引的规则是首先会对复合索引的最左边的,也就是第一个name字段的数据进行排序,在第一个字段的排序基础上,然后再对后面第二个的cid字段进行排序。其实就相当于实现了类似 order by name cid这样一种排序规则。

    所以:第一个name字段是绝对有序的,而第二字段就是无序的了。所以通常情况下,直接使用第二个cid字段进行条件判断是用不到索引的,当然,可能会出现上面的使用index类型的索引。这就是所谓的mysql为什么要强调最左前缀原则的原因。

    那么什么时候才能用到呢?

    当然是cid字段的索引数据也是有序的情况下才能使用咯,什么时候才是有序的呢?观察可知,当然是在name字段是等值匹配的情况下,cid才是有序的。发现没有,观察两个name名字为 c 的cid字段是不是有序的呢。从上往下分别是4 5。

    这也就是mysql索引规则中要求复合索引要想使用第二个索引,必须先使用第一个索引的原因。(而且第一个索引必须是等值匹配)。

    ---------------------------------------------------------------------------------------------------------------------------

    所以对于你的这条sql查询:

    EXPLAIN SELECT * FROM student WHERE cid=1 AND name='小红';

    没有错,而且复合索引中的两个索引字段都能很好的利用到了!因为语句中最左面的name字段进行了等值匹配,所以cid是有序的,也可以利用到索引了。

    你可能会问:我建的索引是(name,cid)。而我查询的语句是cid=1 AND name='小红'; 我是先查询cid,再查询name的,不是先从最左面查的呀?

    好吧,我再解释一下这个问题:首先可以肯定的是把条件判断反过来变成这样 name='小红' and cid=1; 最后所查询的结果是一样的。

    那么问题产生了?既然结果是一样的,到底以何种顺序的查询方式最好呢?

    所以,而此时那就是我们的mysql查询优化器该登场了,mysql查询优化器会判断纠正这条sql语句该以什么样的顺序执行效率最高,最后才生成真正的执行计划。所以,当然是我们能尽量的利用到索引时的查询顺序效率最高咯,所以mysql查询优化器会最终以这种顺序进行查询执行。

    展开全文
  • 这是我 2016 年写的文章,发出来,做索引优化的朋友都可以参考下。名词解释Lucene:高性能的全文检索开源的 Java 工具包。Solr :高性能的利用 java 开发的、开源的,基于 ...全文搜索:利用索引对非结构化数据进行...

    这是我 2016 年写的文章,发出来,做索引优化的朋友都可以参考下。

    名词解释

    Lucene:高性能的全文检索开源的 Java 工具包。Solr :高性能的利用 java 开发的、开源的,基于 Lucene 的搜索服务器。非结构化数据:非结构化的没有固定格式的数据,比如一篇文章等。索引:   利用分词语言处理等手段得到的词与文档 ID 对应关系的数据结构。全文搜索:利用索引对非结构化数据进行搜索的方法。文档:类似于数据库的一条记录,由多个字段组成,是建立索引的基础,索引中的分词是对文档中特定分词字段或不分词字段组成。

    一.背景介绍

    近段时间一直在研究 solr 和 Lucene 相关东西,主要是由于工作需要,需要利用 Solr 来进行日志搜索,但是 Solr 的建索引效率不是很高,难以满足工作中特定日志的性能要求,需要优化其建索引的性能。

    性能的具体要求
    1、在一台机器上普通硬盘的情况下,索引单个文档大小为 200 字节左右,需要达到的效率为 5WTPS。
    2、具有良好的水平扩展性。
    3、对数据备份和数据丢失情况,要求不严格。
    对于以上的性能要求,设计出合理的架构,并建议验证实践。本文没有多少高深的技术,我也是个 solr 和 Lucene 的初学者,只是一个总结,希望起到抛砖引玉的作用。

    二.关于 Solr 建索引优化

    2.1 基本说明

    Solr 是基于 Lucene 开发的,外层封装成 Servlet 形式,运行在 Java 的 Web 容器之中,提供索引分片、多副本等功能,并提供基于 HTTP 的 API,方便调用。
    Solr 的部署有单节点、Master-Salve 模式、SolrCloud 方式。SolrCloud 具有良好的水平扩展性、自动容错性、自动负载均衡等特性,所以这次采用 solrColud 的方式进行索引的优化。
    SolrCloud 中完整的索引为 Collection,这是一个逻辑概念,一个 Collection 由多个 shard 组成,shard 同样为逻辑概念,一个 shard 下面分为多个副本,每份基本相同, 其中一份被选举为 Leader,在建索引的时候通过 Leader 来新建索引。用图表示如下:

    102eb4314b15266ccdc758af30a65a01.png
    image.png

    注:1、红色字体为 Leader,只是个示意,实际上 Leader 是通过选举算法选取出来的。2、Collection 的数据由 shard1 和 shard2 组成,每个 shard 的数据有两份,Collection_shard1_core1 和 Collection_shard1_core2,不同的版本名称可能有差异,对应是一个文件夹,里面保存的是索引的数据。

    2.2 建索引的过程

    为优化 SolrColud 的创建索引的效率,有必要对整个建索引的流程有所了解,建索引的流程如下, 下面描述的建索引过程主要是最常见的通过 SolrJ 方式创建索引,不是采用 DIH 方式创建索引。4813a9fa3cee622660760d9c879e0fe9.png

    简单说明:
    1、客户端发送 HTTP 的 POST 请求到 Solr 服务器,报文格式一般有 xml、json、javabin(只有 java 才支持,二进制结构)。
    2、Web 服务器将请求派发到 Solr 的 Web 应用程序Servlet。
    3、Solr 根据请求的 URI 中的 Collection 名字在 solrConfig.xml 找到注册的/update 消息处理器;这是单个副本的情况下,如果多个副本的情况下,如果需要判断此副本是否为 Leader,如果是非 Leader,则需要将此文档发送给此副本的 Leader,如果是非直接路由模式,Solr 则会根据文档 ID 进行 hash 路由,路由到特定的 Leader 上。
    4、按照 solrConfig.xml 配置的请求处理链来处理索引,比如分词处理器等。
    5、写事务日志,当发送提交后正式将数据写入到存储(初始写入是内存,最后通过硬提交写入磁盘)中。
    6、返回写索引的结果。

    2.3 优化部分

    如果从整体考虑,可以考虑 JVM 调优,通过优化 Web 服务器性能,通过程序和配置等其他方面来建索引。目前通过 JVM 简单的调优和 Web 服务器优化,没有怎么研究,简单的试了下,性能改进不是很大。本文主要考虑程序和其他方面配置方面优化。

    2.3.1 报文批量大小优化

    首先考虑到我们的建索引是通过 HTTP 请求发送的,所以在网络速度固定的情况下,可以通过优化报文大小来提高性能。目前 SolrJ 的接口可以通过 XMl、Javabin 的方式来建索引,Javabin 方式只有 Java 程序可以用,是一种特殊格式,在默认情况下使用 Javabin 方式的报文长度会比 XML 或 JSON 的格式要短,经过测试有部分性能。

    对于 HTTP 请求,我们可以通过控制批次大小,一次发送的合适报文批量大小来进行优化,通过实践,目前 200 个字节左右,发送批量为 1W 左右性能较高。

    2.3.2 路由模式优化

    我们注意到在 Solr 建索引的时候,判断文档属于哪个 shard,需要通过文档 ID 经过 hash 算法,每个文档都要判断一次,这对于性能来说,是不利的,

    这种网络上也有朋友提倡通过直接路由的模式来进行建索引。需要注意的是:1)  索引要特殊方式通过以下 URL 新建:

     http://ip:port/solr/admin/collections?action=CREATE&name=implicit1&shards=shard1,shard2,shard3&router.name=implicit
    1. 在 solr4.x 版本中通过更改 schemal.xml 在 5.x 更改 managed-schema 文件添加以下字段定义:
     "_route_" type="string"/>
    1. 在 solrJ 添加文档的时候需要加入以下字段:
    doc.addField("_route_","shard_x")

    后面的 shard_x 要替换为具体的 shard,比如 shard1 或 shard2 等。通过直接路由模式,多线程的方式,在 solr6.0 版本的情况下,报文 200 个字节左右情况下,单节点的处理效率可以达到 2.5WTPS,比 solr4.9 的单节点 1W 左右 TPS 有较大的提升。另外在测试中发现,报文大小在 200 个字节到 1k 字节之间对 TPS 的影响比较大,当然吞吐量在报文更大的时候会有更好效果。

    53b4e93126310deb5eada2d734d7ef67.png
    直接路由模式

    注意:1、通过这种方式建索引一定要采用多线程同时发送到多个 shard 中去,在 SolrJ 中采用 HttpSolrServer(在 5.x 以后好像已经更改为 HttpSolrClient)  方式进行发送。
    2、如果采用默认的路由模式采用的是 CloudSolrServer 进行发送,CloudSolrServer 内部有负载均衡。3、采用直接路由的模式,如果其中一个 shard 所归属的节点挂掉的话,可能造成数据的丢失。CloudSolrServer 可以通过 zookeeper 上的 clusterstate.json 信息得到具体的 shard 的 leader 的具体 url,直接将 updateRequest 提交给它,不用经过 replica 转发;另外还可以通过随时监听节点的状态变化,来保证可靠性,所以在性能准许的情况下还是不要采用直接路由的模式。

    2.3.3 参数调整优化

    solrconfig.xml 参数优化调整:

    100
    1000

    以上两个参数为建索引的默认值,表示达到这个值的时候,才会将索引刷新到磁盘中去,可以适当调整测试。

    更改建索引线程数:

    16

    这个为建索引的线程数,目前在 4.x 版本中存在,6.0 版本未发现此配置,建议设置为 2*cpuNum,默认为 8 个。更改合并段参数参数:

    10

    索引的存储是按照段为单位的,这个参数决定了多少个段的时候,进行段合并。如果设置的大,则建索引的速度快,但是会导致索引文件多,查询速度慢;相反,如果设置小,则合并段的频率高,加快查询速度,降低了建立索引的速度。

    提交方式的优化:

    ${solr.autoCommit.maxTime:150000}50000true

    自动提交是指在有文档添加的情况下,经过特定的时间间隔或者添加了特定文档数后进行索引的自动提交,设置了自动提交可以在 SolrJ 的代码中不同提交,由于有更新日志的存在,即使在 solr 服务器出现问题的时候,仍然可以在重启 solr 服务器的时候自动恢复索引数据。

    另外参数 openSearcher 表示提交完成后是否重新打开搜索器,打开的会让索引可见。

    注意:自动提交和打开搜索器都是很消耗时间的操作,设置自动提交的文档数量过大的情况下,可能造成建索引的速率产生较大的浮动;

    自动调整在多并发的时候可以防止打开多个搜索器的问题。

    ${solr.autoSoftCommit.maxTime:60000}

    自动软提交,软提交不将索引刷新到存储,所以速率相对比较快,软提交可以让索引立刻可见,故此在要求索引近实时的情况下,可以设置软提交。

    注意如果在自动提交的情况下打开了搜索器,而且延迟时间可以接受的情况下,可以不使用自动软提交。

    三. 结合 Lucene 创建索引

    3.1 基本思路

    从底层来说,Solr 利用的 Lucene 来进行创建索引的,所以在高版本的 Solr 中,只要是相同版本的 Solr 和 Lucene 用的索引文件是兼容的,solrconfig.xml 有使用 Lucene 的版本信息。所以提出一种方案,是否可以通过 Lucene 直接在 Solr 的目录中创建索引,这样就可以减少网络的开销和 HTTP 服务的开销,直接写本地文件效率肯定是更高的。设想如下图所示:fb67380e848e8bdcbffea16a05e821ef.png

    1、客户端调用 Lucene 的 API 直接在本地的 Solr 的 core 的目录建索引。(Collection 一个 shard 的副本其实就是一个 core 文件)
    2、多个客户端,每个客户端对应一个 shard 副本,注意这里是一个 shard 只有一个副本的情况下,如果多个副本可能会导致数据不同步等问题。

    3.2 思路实践

    有了这个思路后,我就进行了实践,在不考虑数据备份的情况下和查询效率的情况下,优先考虑下建索引的效率,发现如下问题:
    1、首先 Lucene 为了防止同一个目录由多个程序在写,加了文件锁,也就是通过了一个叫 write.lock 的文件来控制防止重复写的问题。尝试解决:
    到的第一个方法是看看有没有办法进行解锁,Lucene 的 4.9 版本里面还真有个解锁的方法:

        if (IndexWriter.isLocked(index)) {
             try {
                IndexWriter.unlock(index);
             } catch (Exception e) {
                print_exception_trace(e);
             }
        }

    但是这个方法,调用起来看起来是成功的,但是在真正往 solr 的目录进行写索引的时候仍然报错。遂放弃。这个思路本来没错的,既然在 solr 的索引目录无法再创建 Lucene 的索引,那么可以考虑在其他的目录创建索引,然后再合并到 solr 的索引中去。

    103f380a539ff45bff633c841b04e44c.png
    合并lucene索引方式

    过程说明:

    1、 客户端程序调用 lucene 的 API 进行写索引。
    2、 索引写到特定的目录下。
    3、 调用 solr 的索引合并的 HTTP 接口,进行索引合并。
    4、 调用 HTTP 的合并结构后会将 Lucene 新建的索引目录合并到 Solr 的索引中去。

    注意:1、 这种合并的 URL 如下:

    http://ip:port/solr/admin/cores?action=mergeindexes&core=collection_shard1_replica1&indexDir=/parkfs01/aus/soft/luncenetmp/0

    2、 合并后的索引不是可见的,需要重新加载索引,或者重新做提交,提交时候需要打开搜索器使索引可见:

     http://ip:port/ solr/collection/update?commit=true&openSearcher=true

    这里的 collection 要改成具体的 collection 名字。在单节点时候需要重新加载整个 core,

    这个耗时很大,单节点仅仅提交,仍然搜索不到新添加的文档。

    3、如果在一个目录下进行新建 Lucene 索引,需要删除目录后以备下次重写。

    3.3 架构设计

    方案一:

    对于改造后的思路,设计了一种模式来进行建索引和提交并发进行,设计的结构如下:a3db96d552ca2953f880ec83dad72186.png

    说明:

    1、文档生成线程是根据数据生成所需要建索引的文档集合。
    2、文档集合生成后,发送到中间队列中去。3、有一个线程池,里面有 N 多线程,负责取文档集合,写入本地的索引文件夹中去, 注意一个线程对应一个 IndexWriter,一个 IndexWriter 对应一个文件夹。
    4、将需要合并的 URL 和提交的 URL,发送到合并和提交队列中去。
    5、提交合并线程池取到需要合并的 URL 和提交的 URL,先进行合并,然后提交。
    6、提交后,为了让文件夹再次循环利用需要删除文件夹内容。

    注意:
    1、solr 的提交操作是很耗时的,在实际中,可以通过定时提交等手段进行进一步优化,不过 solr 本身设置的定时提交是无法起作用的。
    2、在删除目录数据之前对于 4.x 版本需要进行 IndexWriter 的删除索引动作,不删除索引直接写会存在段信息错误的问题。
    3、对于 lucene 的 6.0 版本,在删除文件的时候需要保存加锁文件 write.lock;不能通过删除索引的方式进行索引信息的清理,不然数据仍然有问题,直接删除文件即可。
    4、以上设计经过测试,效率并没有高多少,也就是 2WTPS 左右。

    方案二:

    经过方案一的测试,发现速度并没有达到预期,方案一本想通过各个环节分离来达到并行的最大速率的目的,结果并不如意,经过分析后设计第二套方案,如图:

    39ffb08aea28757b096fa82bc34a4797.png
    方案二

    说明:
    1、根据要求生成文档。
    2、根据生成的文档列表生成可执行单元,可以执行单元的主要是创建 IndexWriter 和添加索引动作。
    3、将可行对象发送给线程池执行。
    4、执行完毕后将需要合并的索引目录和 url 发送到合并队列,合并队列数量达到一定数量后,执行合并索引动作和提交索引动作。
    5、索引线程池存在建立一定数量索引后,会关闭原来的 IndexWriter,从新创建的目录生成新的 IndexWriter。

    注意:
    1、因为 IndexWriter 是线程安全的,所以线程池可以共同操作同一个 IndexWriter 对象。
    2、在合并索引后,不能立刻删除目录,调用 SOLR 的合并索引的 URL 返回后,后台也有可能还在合并。
    3、经过测试在一个索引文档 286 个字节条件下,solr6.0 版本,速率大概在 4.7W 和 5.1W 之间浮动。

    方案三:方案二测试的速率不太稳定,而且需要定时执行删除索引文件,提交和合并索引的速率还是比较慢。需要合并、提交索引和删除索引文件的根本在于 Lucene 的索引和 solr 的索引不在同一个目录,写同一个目录测试有问题的是 4.9 版本,所以想在 solr6.0 版本上测试试试。结果在 solr6.0 版本,通过直接程序删除 write.lock 后,可以将索引直接写到 solr 的索引目录里面去。但是如果让数据可见,就必须重新 reload 整个索引副本,在 reload 整个索引副本后,数据可以查询,但是由于我们删除了 write.lock,导致了重新 reload 的 solr 日志存在部分错误信息。简单的测试结果如下:
    1、测试环境:2 台机器,2 个 solr 节点,实际使用一个节点,配置:64G 内存、16CPU。
    2、线程个数:1 个。
    3、按照报文大小分别为 0.2k、1k、2k 测试结果如下:

    序号报文大小(字节)速率(TPS)吞吐量(MB/s)
    1286510889.9
    212283790044
    324063800084
    展开全文
  • 索引只是一个提高效率的因素,mysql索引的几种类型: 4)、单值索引,只包含一...几种索引结构: Hash索引 full-text全文索引 R-Tree 索引 BTree索引 哪些情况要创建索引。 1)、主自动建立唯一索引 2)...

    索引只是一个提高效率的因素,mysql索引的几种类型:

    4)、单值索引,只包含一个列,一张表可以有多个单值索引。

    5)、唯一索引,索引列的值必须唯一,允许为空。

    6)、复合索引,包含多个列。

     7)、索引的相关操作

     

    几种索引结构:

    Hash索引

    full-text全文索引

    R-Tree 索引

    BTree索引

     

    哪些情况要创建索引。

    1)、主建自动建立唯一索引

    2)、频繁作为查询条件的字段应该创建索引

    3)、查询中与其他表关联的字段,外建关系建立索引。

    4)、频繁更新的字段,不适合创建索引

    5)、where条件里用不到的字段补创建索引。

    6)、单建或者组合索引的选择问题,在高并发下倾向于创建复合索引

    7)、查询中排序的字段,排序的字段如果按照索引去访问,将提高效率

    8)、查询中统计或者分组字段

    7、哪些情况不需要创建索引

    1)、表记录太少

    2)、经常增删的表

    3)、数据重复且分布平均的字段。
     

    展开全文
  • 我们在下一篇讨论索引列次序的问题,首先看一下列独立索引的情况,以下面的表结构为例:CREATE TABLE test (c1 INT,c2 INT,c3 INT,KEY(c1),KEY(c2),KEY(c3),);使用这种索引策略通常是一些权威的建议(例如在WHERE...

    通常会对多列索引缺乏理解,常见的错误是将很多列设置独立索引,或者是索引列使用错误的次序。我们在下一篇讨论索引列次序的问题,首先看一下多列独立索引的情况,以下面的表结构为例:

    CREATE TABLE test (

    c1 INT,

    c2 INT,

    c3 INT,

    KEY(c1),

    KEY(c2),

    KEY(c3),

    );

    使用这种索引策略通常是一些权威的建议(例如在WHERE条件中用到的条件列增加索引)的结果。事实上,这是大错特错的,要评分的话顶多给1颗星。这种方式的索引与真正优化的索引相比,要慢上几个数量级。有时候当年不能设计三星以上的索引时,去关注优化行次序或者创建覆盖索引都比忽略WHERE条件强。

    覆盖索引(covering index)指一个查询语句的执行只用从索引中就能够取得,不必从数据表中读取。也可以称之为实现了索引覆盖。 当一条查询语句符合覆盖索引条件时,MySQL只需要通过索引就可以返回查询所需要的数据,这样避免了查到索引后再返回表操作,减少I/O提高效率。 如,表covering_index_sample中有一个普通索引 idx_key1_key2(key1,key2)。当我们通过SQL语句:select key2 from covering_index_sample where key1 = ‘keytest’;的时候,就可以通过覆盖索引查询,无需回表。

    对很多列创建独立的索引在很多情况下,并不能帮助MySQL改善性能。MySQL 5.0及更新的版本可以使用索引合并策略对这类设计进行些许的优化 —— 这种方式允许在有多列索引的数据表中的查询中限制在索引的使用去定位所需的数据行。

    index merge 是对多个索引分别进行条件扫描,然后将它们各自的结果进行合并(intersect/union)

    早期的MySQL版本只能使用一个索引,因此当没有索引辅助时,MySQL通常进行全表扫描。例如在film_actor表有一个film_id和actor_id索引,但是在WHERE条件中同时使用这两个索引并不是一个好的选择:

    SELECT film_id, actor_id FROM film_actor WHERE actor_id = 1 OR film_id = 1;

    在早期的MySQL版本中,除非你像下面的语句一样将两个查询联合起来,否则这个查询会导致全表扫描。

    SELECT film_id, actor_id FROM film_actor WHERE actor_id = 1 UNION ALL

    SELECT film_id, actor_id FROM film_actor WHERE film_id = 1 AND actor_id <> 1;

    在MySQL 5.0之后的版本中,查询会同时使用两个索引并且合并最终的结果。需要三个变体的算法实现这个过程:

    使用OR条件获取并集(union)数据

    使用AND条件获取交集数据

    将上面两个步骤的数据的交集再取并集。

    上面有点费解,其实应该是分布使用单个条件(以便使用索引)查出全部数据,然后再组合数据。下面使用EXPLAIN查看一下。

    EXPLAIN SELECT `film_id`,`actor_id` FROM `film_actor` WHERE `actor_id`=1 OR `film_id`=1

    b6fa1378010801758af6b7a07d3dbf04.png

    image

    可以看到查询方式是全表扫描,但是使用了Extra做优化。MySQL在处理负责查询时会使用这种技巧,因此你可能会在Extra中看到嵌套操作。这种索引合并的策略有些时候会发挥很好的作用,但更多的时候应该当作是对差劲索引使用的一个指示:

    当服务器使用交集索引(通常是使用AND条件),通常意味着你需要一个索引包含所有相关的列,而不是独立的索引列再组合。

    当服务器使用并集索引(通常是使用OR条件),有时候缓存、排序和合并操作会占用很多的CPU和内存资源,尤其是索引并不都是具备筛选的时候,这会导致扫描返回大量的数据行供合并操作。

    记住优化器并不承担这些成本——它仅仅是优化随机页读取的数量。这会使得查询“掉价”,导致全表扫描造成事实上更慢。CPU和内存的高占用会影响并发查询,但这些影响在你单独运行查询语句时并不会发生。因此,有时候像在MySQL 4.1版本那样重写那些使用UNION的查询会得到更优的效果。

    当你使用EXPLAIN分析的时候看到了索引合并,你应该检查查询语句和表结构,看看是不是最优的方式。你可以使用optimizer_switch(优化开关)禁用索引合并来检查。

    再将film_actor的索引改为联合索引(删除原先的两列独立索引film_id和actor_id)看一下效果,可以看到此时避免了全表查询。

    ALTER TABLE film_actor ADD INDEX `sindex` (`film_id`,`actor_id`);

    902e37166c8b73c42ea2813aa59b77ee.png

    image

    展开全文
  • 调用lucene向solr建索引实践

    千次阅读 2017-03-21 16:04:06
    Solr的底层是基于Lucene索引结构,Lucene是一套信息检索工具包,...如果我们直接利用Lucene来写Solr的索引目录,可以减去很网络开销,并且减去Solr除了索引以外功能做的额外开销,从提升建索引的角度,有不错的提升。
  • 深入了解-数据库建索引

    万次阅读 2018-05-01 11:03:02
    我们先看看索引的定义:[在关系数据库中,索引是一种单独的、物理的对数据库表中一列或列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。...
  • 建个索引试试吧,嗯,果然有了索引速度就快了很,索引就是目录,建索引和不建索引的区别就是翻整本书和发目录的区别,那个快就一步了然了。一句话 索引的出现其实就是为了提高数据查询的效率,就像...
  • (一张表最多允许建16个索引)(下面这张图为计算机组成原理内容,每查询一次索引节点,都会进行一次磁盘IO读取,即要寻道和旋转)二、MySQL索引结构为什么是B+树?MySQL 建索引可使用的数据结构有B+树和Hash两种,但是...
  • 但是因为数据量大的原因,索引添加可能不成功,想了很办法,终于挖坑成功。开始准备工作,user表结构:CREATE TABLE`users` (`id`int(11) unsigned NOT NULLAUTO_INCREMENT,`name`varchar(255) CHARACTER ...
  • 1 key 是数据库的物理结构,它包含两层意义,一是约束(偏重于约束和规范数据库的结构完整性),二是索引(辅助查询用的)。包括primary key, unique key, foreign key 等。primary key 有两个作用,一是约束作用...
  • 一、何为索引?1、 索引是帮助数据库高效获取数据的 排好序 的 数据结构 。...MySQL 建索引可使用的数据结构有 B+树 和 Hash 两种,但是Hash用得很少, 优点是可以快速定位到某一行,缺点是不能解决范围...
  • 我们先看下面这组关于动物的文章在行式数据库中的存储表结构如下:如果在常用...B-Tree/B+Tree 是结合磁盘的读取特性(顺序读/随机读)来提升数据读取效率的存储结构,它可以减少磁盘寻道次数,将个值作为一个数组通...
  • (下面这张图为计算机组成原理内容,每查询一次索引节点,都会进行一次磁盘IO读取,即要寻道和旋转)二、MySQL索引结构为什么是B+树?MySQL 建索引可使用的数据结构有B+树和Hash两种,但是Hash用得很少, 优点是可以...
  • 索引是对数据库表中的一列或列值进行排序的一种结构,使用索引可以快速访问数据库表中的特定信息。二、索引的作用?索引相当于图书上的目录,可以根据目录上的页码快速找到所需的内容,提高性能(查询速度)三、优点...
  • 2、索引,更新数据的速度越慢。 3、尽量在采用MyIsam作为引擎的时候使用索引(因为MySQL以BTree存储索引),而不是InnoDB。但MyISAM不支持Transcation。 4、当你的程序和数据库结构/SQL...
  • “基础不是100分考60分,而是摩天大楼的地基。” 为什么需要索引? (1)在实际的软件开发工作的本质都可以抽象为“对数据的存储和计算”。对应到数据结构和算法中,那“存储”需要的就是数据结构,“计算”需要...
  • 当我们去设计数据库表结构,对操作数据库时(尤其是查表时的SQL语句),我们都需要注意数据操作的性能。这里,我们不会讲过 的SQL语句的优化,而只是针对MySQL这一Web应用最多的数据库。希望下面的这些优化技巧对你...
  • 一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上索引的优点类似大学图书馆书目索引,提高数据检索的效率,降低数据库的IO成本通过索引列对数据进行排序,降低数据排.....
  • Lucene索引文件结构速览

    千次阅读 2012-11-05 15:35:57
    Lucene的索引结构是有层次结构。 每个层次都保存了本层次的信息以及下一层次的元信息。 1) 索引Index  在Lucene中,一个索引是放在一个文件夹中的 2) 段Segment  一个索引可以包含个段,段与段之间是独立...
  • 例如几乎每个程序员都要打交道的数据库,如果仅仅是用来存个数据、建建表、建建索引、做做增删改查,那么也许觉得数据结构和这东西没什么关系。不过要是哪天心血来潮,想知道的一点,想研究一下如何优化数据库,...
  • 如果我理解正确,这个查询应该有效:SELECT id FROM testTag WHERE LOCATE('bar', CONCAT(tag1,'...鉴于此表结构:CREATE TABLE `testTag` (`id` int(11) NOT NULL,`tag1` varchar(10) DEFAULT NULL,`tag2` varchar(1...
  • 原文:SQL Server 索引和表体系结构(非聚集索引)非聚集索引 ...非聚集索引和聚集索引一样都是B-树结构,但是非聚集索引不改变数据的存储方式,所以一个表允许建多个非聚集索引;非聚集索引的叶层是由索引页而不是由...
  • 建议 一张表最多建索引不要超过5个。 分组之前必排序 单值索引 一个索引只包含单个列,一个表可以有个单列索引。 建议 一张表最多建索引不要超过5个 排序尽量遵守所建索引的顺序和个数。 group by 尽量遵守所...
  • MySQL索引的数据结构以及算法原理

    万次阅读 多人点赞 2018-04-19 22:13:28
    写在前面的话 在编程领域有一句人尽皆知的法则“程序 = 数据结构 + 算法”,我个人是不太赞同这句话...例如几乎每个程序员都要打交道的数据库,如果仅仅是用来存个数据、建建表、建建索引、做做增删改查,那么...
  • 谈到数据库优化,我想大家肯定听说过慢查询,当然第一个想到的肯定是建索引,或者是建合适的索引,那么为什么建立索引就可以有效的解决查询速度慢的问题呢?联合索引的最左匹配原则它的底层机理又是怎样的呢?索引越性能...
  • 一 写在前面的话在编程领域有一句人尽皆知的法则“程序 = 数据结构 算法”,我个人是不太赞同...例如几乎每个程序员都要打交道的数据库,如果仅仅是用来存个数据、建建表、建建索引、做做增删改查,那么也许觉得数据结
  • 例如几乎每个程序员都要打交道的数据库,如果仅仅是用来存个数据、建建表、建建索引、做做增删改查,那么也许觉得数据结构和这东西没什么关系。不过要是哪天心血来潮,想知道的一点,想研究一下如何优化...
  • 最终效果Laravel Gii 为中小型项目快速创建管理后台,提供了一种新的可能。使用的过程中,你会发现很轻量,自由度很高,...你会发现它没有提供用户登录、权限功能,转而只是提供更加轻量化的页面创建,这点会让很...

空空如也

空空如也

1 2 3 4 5 ... 18
收藏数 343
精华内容 137
关键字:

多建索引结构