Spring 的 @Lookup 注解使用

最近工作中重构代码,需要将prototype类型的组件注入到singleton类型的组件中,但是只是声明scope是prototype,并使用@autowire注入的话,并不能满足需要。个人理解是项目启动的时候已经组装好了,导致单例bean中的原型bean也是同一个。

1. 介绍

我们来看一下如何通过方法级的@Lookup注解完成依赖注入。

2. 为什么用@Lookup?

一个有@Lookup注解的方法会告诉Spring,当我们调用这个方法时,Spring会返回一个方法返回值类型的实例。
实质上,Spring会父爱我们的注解方法并使用我们方法的返回值和参数作为BeanFactory#getBean方法的入参。
@Lookup注解的使用情景:

1) 向一个单例bean注入一个原型bean(prototype-scoped bean)(类似于Provider)
2) Injecting dependencies procedurally(暂译为程序依赖注入,有不妥请指正)
@Lookup相当于XML元素中的lookup-method

3. 如何使用@Lookup

3.1 向一个单例bean注入原型bean

当我们决定使用一个原型bean时,我们必须面对的问题就是我们的单例bean要如何使用这些原型bean呢?
当然可以使用Provider,但是@Lookup在某些方面更合适一些。
首先,我们先创建一个之后需要注入到单例bean的原型bean。

之后我们使用@Lookup创建一个单例bean:

使用@Lookup,我们能在单例bean中得到一个SchoolNotification实例。

注意,在StudentServices中,我们将getNotification方法设置成了一个空方法(we left the getNotification method as a stub)。
这是因为,spring通过调用beanFactory.getBean(StudentNotification.class)重写了这个方法,所以我们能将它置空。
3.2 部分就是说使用@Lookup注入的话,还可以通过构造器传参,其实就是spring调用beanFactory.getBean(class, name)实现的。

示例

下面看一个例子:




可以看到,使用@lookup时,两次的MyHandlerImpl不是同一个对象,而使用autowired注入的话,则是同一个对象。
需要注意的是,被@lookup注解的方法需要是public的哦!

 

0

Win10系统2020最新激活密钥KEY

Win10系统免费升级的活动持续进行当中,相信有不少用户会将win7/win8系统升级到Win10,但是升级后会发现需要激活码进行激活。不想购买的话,只能去网上寻找,而不同版本所使用的激活码是不一样的,这样操作起来非常麻烦。小编这里整理了些2020最新的win10激活密钥,对应各种版本,亲测有效。

  win10永久激活密钥:

  一、win10专业版

W269N-WFGWX-YVC9B-4J6C9-T83GX

MH37W-N47XK-V7XM9-C7227-GCQG9

2X7P3-NGJTH-Q9TJF-8XDP9-T83GT

J2WWN-Q4338-3GFW9-BWQVK-MG9TT

NBQWQ-W9PTV-B4YWP-4K773-T6PKG

236TW-X778T-8MV9F-937GT-QVKBB

87VT2-FY2XW-F7K39-W3T8R-XMFGF

KH2J9-PC326-T44D4-39H6V-TVPBY

TFP9Y-VCY3P-VVH3T-8XXCC-MF4YK

J783Y-JKQWR-677Q8-KCXTF-BHWGC

C4M9W-WPRDG-QBB3F-VM9K8-KDQ9Y

2VCGQ-BRVJ4-2HGJ2-K36X9-J66JG

MGX79-TPQB9-KQ248-KXR2V-DHRTD

FJHWT-KDGHY-K2384-93CT7-323RC

  二、常用笔记本激活码:

戴尔DELL序列号:342DG-6YJR8-X92GV-V7DCV-P4K27

联想LENOVO序列号:22TKD-F8XX6-YG69F-9M66D-PMJBM

三星SAMSUNG序列号:49PB6-6BJ6Y-KHGCQ-7DDY6-TF7CD

宏基ACER序列号:YKHFT-KW986-GK4PY-FDWYH-7TP9F或FJGCP-4DFJD-GJY49-VJBQ7-HYRR

  三、win10各版本密钥:

  1、神Key(适用各版本):

KH2J9-PC326-T44D4-39H6V-TVPBY

TFP9Y-VCY3P-VVH3T-8XXCC-MF4YK

236TW-X778T-8MV9F-937GT-QVKBB

87VT2-FY2XW-F7K39-W3T8R-XMFGF

6K2KY-BFH24-PJW6W-9GK29-TMPWP

RHTBY-VWY6D-QJRJ9-JGQ3X-Q2289

企业版:XGVPP-NMH47-7TTHJ-W3FW7-8HV2C

教育版:YNMGQ-8RYV3-4PGQ3-C8XTP-7CFBY

专业版N:2B87N-8KFHP-DKV6R-Y2C8J-PKCKT

企业版N:WGGHN-J84D6-QYCPR-T7PJ7-X766F

教育版N:84NGF-MHBT6-FXBX8-QWJK7-DRR8H

企业版S:FWN7H-PF93Q-4GGP8-M8RF3-MDWWW

单语言版:BT79Q-G7N6G-PGBYW-4YWX6-6F4BT

Win10和Office2016官方KMS序列号激活密钥,win1010240KMS激活密钥

先用win10预览版本的序列号去激活,如果还不行的话则可以使用这个序列号。

  2通用版win10密匙:

VK7JG-NPHTM-C97JM-9MPGT-3V66T

NPPR9-FWDCX-D2C8J-H872K-2YT43

W269N-WFGWX-YVC9B-4J6C9-T83GX

NYW94-47Q7H-7X9TT-W7TXD-JTYPM

NJ4MX-VQQ7Q-FP3DB-VDGHX-7XM87

MH37W-N47XK-V7XM9-C7227-GCQG9

VK7JG-NPHTM-C97JM-9MPGT-3V66T

  下面是各win10版本的序列号:

win10CoreSingleLanguage:JPYNJ-XTFCR-372YJ-YJJ4Q-G83YB

win10Core中文版LanguageEdition:R3BYW-CBNWT-F3JTP-FM942-BTDXY

win10Core:KTNPV-KTRK4-3RRR8-39X6W-W44T3

win10Pro:8N67H-M3CY9-QT7C4-2TR7M-TXYCV

win10Enterprise:CKFK9-QNGF2-D34FM-99QX3-8XC4K

win10CoreSingleLanguage:JPYNH-XTFCR-372YJ-YJJ3Q-G83YB

win10CoreChineseLanguangeEdition:R3BYW-CBNWT-F3JTP-FM942-BTDXY

  win10企业版:

win10Enterprise:NPPR9-FWDCX-D2C8J-H872K-2YT43

win10EnterpriseN:DPH2V-TTNVB-4X9Q3-TJR4H-KHJW4

win10Enterprise2015LTSB:WNMTR-4C88C-JK8YV-HQ7T2-76DF9

win10Enterprise2015LTSBN:2F77B-TNFGY-69QQF-B8YKP-D69TJ

  激活方法:

系统安装完毕后,首先以管理员身份打开CMD命令行窗口,按下Win+X,选择命令提示符(管理员)。

说明:kms.xspace.in是kms服务器地址,可能会失效,如果激活失败,可以自行搜索kms服务器地址,将kms.xspace.in替换成新的地址即可,比如换成kms.03k.org,参考可用的kms激活服务器有哪些

  win10专业版用户请依次输入:

slmgr/ipkW269N-WFGWX-YVC9B-4J6C9-T83GX

slmgr/skmskms.03k.org

slmgr/ato

  win10企业版用户请依次输入:

slmgr/ipkNPPR9-FWDCX-D2C8J-H872K-2YT43

slmgr/skmskms.03k.org

slmgr/ato

  win10家庭版用户依次输入:

slmgr/ipkTX9XD-98N7V-6WMQ6-BX7FG-H8Q99

slmgr/skmskms.03k.org

slmgr/ato

以上就是2020最新的win10激活密钥,因为使用次数有限,有需要的赶紧使用吧。

0

springboot 设置默认的对象转 json 字符串时属性为 null 时不显示

springboot框架中在controller层使用@RestController注解,会将对象自动转换为json格式发送到前端。对象中会存在值为null的属性。如果不想在json数据中显示值为null的键值对,在配置文件中写入下面的代码

或者在实体类中通过注解@JsonInclude(Include.NON_NULL)挨个配置

配置前

配置后

 

0

编写数据库 sql 给表里某列添加唯一约束

假设我们有一个mysql数据库,建立了一个user表,字段分别是id,username,password。

主键是id,username是不可以重复的,所以需要给username添加唯一性约束。

添加语句如下

语句解释

注意事项

当你表中要添加唯一约束的列中有重复的值时会添加约束失败,这时把重复的值删除就可以了。

0

JVM 有哪些重要的性能参数

针对垃圾收集和内存,有 600 多个参数可以传递给JVM来配置。如果再包括其他方面,则 JVM 参数总数将超过 1000+。对于大多数人或者场合来说,这显然无法让人抓住重点。那 JVM 有哪些重要的性能参数呢?本文将重点介绍6个重要的JVM参数,在Java性能测试中起着非常重要的作用。

-Xmx 和-XX:MaxMetaspaceSize

-Xmx可能是最重要的JVM参数。-Xmx定义要分配给应用程序的最大堆大小。。您可以这样定义应用程序的堆大小:-Xmx2g

堆大小在影响应用性能和所需物理硬件需求。这带来了一个问题,我的应用程序正确的堆大小是多少?我应该为应用程序分配大堆大小还是小堆大小?答案是:取决于需求和预算。

-Xms-Xmx设置为相同值的会提高 JVM 性能

元空间是将存储JVM的元数据定义(例如类定义,方法定义)的区域。默认情况下,可用于存储此元数据信息的内存量是无限的(即受您的容器或计算机的 RAM 大小的限制)。您需要使用-XX:MaxMetaspaceSize参数来指定可用于存储元数据信息的内存量的上限。

-XX:MaxMetaspaceSize=256m

GC 算法

OpenJDK 中有 7 种不同的 GC 算法:

  • Serial GC
  • Parallel GC
  • Concurrent Mark & Sweep GC
  • G1 GC
  • Shenandoah GC
  • Z GC
  • Epsilon GC

如果您未明确指定 GC 算法,那么 JVM 将选择默认算法。在 Java 8 之前,Parallel GC是默认的 GC 算法。从 Java 9 开始,G1 GC是默认的 GC 算法。

GC 算法的选择对于确定应用程序的性能起着至关重要的作用。根据我们的研究,我们正在使用 Z GC 算法观察到出色的性能结果。如果使用JVM 11+,则可以考虑使用Z GC算法(即-XX:+ UseZGC)。

下表总结了激活每种垃圾收集算法所需传递的 JVM 参数。

GC 算法 JVM 参数
Serial GC -XX:+ UseSerialGC
Parallel GC -XX:+ UseParallelGC
Concurrent Market & Sweep (CMS) GC -XX:+ UseConcMarkSweepGC
G1 GC -XX:+ UseG1GC
Shenandoah GC -XX:+ 使用 ShenandoahGC
Z GC -XX:+ UseZGC
Epsilon GC GC -XX:+ UseEpsilonGC

启用 GC 日志记录

垃圾收集日志包含有关垃圾收集事件,回收的内存,暂停时间段等信息,可以通过传递以下 JVM 参数来启用垃圾收集日志:

从 JDK 1 到 JDK 8:

-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:{file-path}

从 JDK 9 及更高版本开始:

-Xlog:gc*:file={file-path}

Demo:

通常,GC 日志用于调整垃圾回收性能。但是,GC 日志包含重要的微观指标。这些指标可用于预测应用程序的可用性和性能特征。在本文中将重点介绍一种这样的标尺:GC 吞吐量。GC 吞吐量是您的应用程序在处理客户交易中花费的时间与它在处理 GC 活动中花费的时间之比。假设您的应用程序的 GC 吞吐量为 98%,则意味着应用程序将其 98%的时间用于处理客户活动,其余 2%用于 GC 活动。

现在,让我们看一个健康的 JVM 的堆使用情况图:

JVM 有哪些重要的性能参数

您会看到一个完美的锯齿图案。您会注意到,当运行 Full GC(红色三角形)时,内存利用率将一直下降到最低。

现在,让我们看一下有问题的 JVM 的堆使用情况图:

JVM 有哪些重要的性能参数

您可以注意到,在图表的右端,即使 GC 反复运行,内存利用率也没有下降。这是一个典型的内存泄漏迹象,表明该应用程序正在存在某种内存问题。

如果您仔细观察一下该图,您会发现重复的完整 GC 开始在上午 8 点左右开始。但是,该应用程序仅在上午 8:45 左右开始获取 OutOfMemoryError。到上午 8 点,该应用程序的 GC 吞吐量约为 99%。但是,在上午 8 点之后,GC 吞吐量开始下降到 60%。因为当重复的 GC 运行时,该应用程序将不会处理任何客户交易,而只会进行 GC 活动。

-XX:+ HeapDumpOnOutOfMemoryError,-XX:HeapDumpPath

OutOfMemoryError是一个严重的问题,它将影响您的应用程序的可用性和性能。要诊断OutOfMemoryError或任何与内存相关的问题,必须在应用程序开始遇到OutOfMemoryError的那一刻或一瞬间捕获堆转储。由于我们不知道何时会抛出OutOfMemoryError,因此很难在抛出时左右的正确时间手动捕获堆转储。但是,可以通过传递以下 JVM 参数来自动化捕获堆转储:

-XX:+ HeapDumpOnOutOfMemoryError和-XX:HeapDumpPath = {HEAP-DUMP-FILE-PATH}

-XX:HeapDumpPath中,需要指定堆转储所在的文件路径。传递这两个 JVM 参数时,将在抛出OutOfMemoryError时自动捕获堆转储并将其写入定义的文件路径。例:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/crashes/my-heap-dump.hprof

一旦捕获了堆转储,就可以使用HeapHeroEclipseMAT之类的工具来分析堆转储。

-Xss

每个应用程序将具有数十,数百,数千个线程。每个线程都有自己的堆栈。在每个线程的堆栈中,存储以下信息:

  • 当前执行的方法/功能
  • 原始数据类型
  • 变量
  • 对象指针
  • 返回值。

他们每个都消耗内存。如果它们的使用量超出某个限制,则会引发StackOverflowError。可以通过传递-Xss 参数来增加线程的堆栈大小限制。例:

-Xss256k

如果将此-Xss值设置为一个很大的数字,则内存将被阻塞并浪费。假设您将-Xss值指定为2mb,而只需要256kb,那么您将浪费大量的内存。

假设您的应用程序有 500 个进程,然后-Xss值为2Mb,则您的线程将消耗1000Mb的内存。另一方面,如果您仅将-Xss分配为256kb,那么您的线程将仅消耗125Mb的内存。每个 JVM 将节省875Mb内存。

注意:线程是在堆(即-Xmx)之外创建的,因此这1000Mb将是您已经分配的-Xmx 值的补充。

-Dsun.net.client.defaultConnectTimeout 和-Dsun.net.client.defaultReadTimeout

现代应用程序使用多种协议(即 SOAP,REST,HTTP,HTTPS,JDBC,RMI)与远程应用程序连接。有时远程应用程序可能需要很长时间才能做出响应,有时它可能根本不响应。

如果没有正确的超时设置,并且远程应用程序的响应速度不够快,则您的应用程序线程/资源将被卡住。远程应用程序无响应可能会影响您的应用程序的可用性。它可以使您的应用程序停止磨削。为了保护应用程序的高可用性,应配置适当的超时设置。

您可以在 JVM 级别传递这两个强大的超时网络属性,这些属性可以全局适用于所有使用java.net.URLConnection的协议处理程序:

sun.net.client.defaultConnectTimeout:指定建立到主机的连接的超时(以毫秒为单位)。例如,对于 HTTP 连接,它是与 HTTP 服务器建立连接时的超时。当建立与资源的连接时,sun.net.client.defaultReadTimeout指定从输入流读取时的超时(以毫秒为单位)。
例如,如果您要将这些属性设置为 2 秒:

注意,默认情况下,这两个属性的值为-1,这表示未设置超时。

0

MySQL 全文索引模糊查询 Match Against 与 Like 比较

1.概要

InnoDB引擎对FULLTEXT索引的支持是MySQL5.6新引入的特性,之前只有MyISAM引擎支持FULLTEXT索引。对于FULLTEXT索引的内容可以使用MATCH()…AGAINST语法进行查询。

为了在InnoDB驱动的表中使用FULLTEXT索引MySQL5.6引入了一些新的配置选项和INFORMATION_SCHEMA表。比如,为了监视一个FULLTEXT索引中文本处理过程的某一方面可以查询INNODB_FT_CONFIG,INNODB_FT_INDEX_TABLE,INNODB_FT_INDEX_CACHE,INNODB_FT_DEFAULT_STOPWORD,INNODB_FT_DELETED和INNODB_FT_BEING_DELETED这些表。可以通过innodb_ft_num_word_optimize和innodb_optimize_fulltext_only选项控制OPTIMIZETABLE命令对InnoDB FULLTEXT索引的更新。

2.相关库表

INFORMATION_SCHEMA库中与InnoDB全文索引相关的表如下:

INNODB_SYS_INDEXES:提供了InnoDB索引的状态信息。
INNODB_SYS_TABLES:提供了InnoDB表的状态信息。
INNODB_FT_CONFIG:显示一个InnoDB表的FULLTEXT索引及其相关处理的元数据。
INNODB_FT_INDEX_TABLE:转化后的索引信息用于处理基于InnoDB表FULLTEXT索引的文本搜索。一般用于调试诊断目的。使用该表前需先配置innodb_ft_aux_table配置选项,将其指定为想要查看的含FULLTEXT索引的InnoDB表,选项值的格式为database_name/table_name。配置了该选项后INNODB_FT_INDEX_TABLE,INNODB_FT_INDEX_CACHE, INNODB_FT_CONFIG, INNODB_FT_DELETED和INNODB_FT_BEING_DELETED表将被填充与innodb_ft_aux_table配置选项指定的表关联的搜索索引相关信息。
INNODB_FT_INDEX_CACHE:向含FULLTEXT索引的InnoDB表插入数据后新插入数据转后的索引信息。表结构与INNODB_FT_INDEX_TABLE一致。为含FULLTEXT索引的InnoDB表执行DML操作期间重组索引开销很大,因此将新插入的被索引的词单独存储于该表中,当且仅当为InnoDB表执行OPTIMIZE TABLE语句后才将新的转换后的索引信息与原有的主索引信息合并。使用该表前需先配置innodb_ft_aux_table配置选项。
INNODB_FT_DEFAULT_STOPWORD:在InnoDB表上创建FULLTEXT索引所使用的默认停止字表。
INNODB_FT_DELETED:记录了从InnoDB表FULLTEXT索引中删除的行。为了避免为InnoDB的FULLTEXT索引执行DML操作期间重组索引的高开销,新删除的词的信息单独存储于此表。当且仅当为此InnoDB表执行了OPTIMIZE TABLE操作后才会从主搜索索引中移除已删除的词信息。使用该表前需先配置innodb_ft_aux_table选项。
INNODB_FT_BEING_DELETED:为含FULLTEXT索引的InnoDB表执行OPTIMIZE TABLE操作时会根据INNODB_FT_DELETED表中记录的文档ID从InnoDB表的FULLTEXT索引中删除相应的索引信息。而INNOFB_FT_BEING_DELETED表用于记录正在被删除的信息,用于监控和调试目的。

3.相关配置选项

Name Cmd-
Line
Option file System Var Status Var Scope Dynamic
innodb_ft_aux_table:指定包含FULLTEXT索引的InnoDB表的的名称。该变量在运行时设置用于诊断目的。设置该值后INNODB_FT_INDEX_TABLE, INNODB_FT_INDEX_CACHE, INNODB_FT_CONFIG,INNODB_FT_DELETED和INNODB_FT_BEING_DELETED表将被填充与innodb_ft_aux_table指定的表关联的搜索索引相关信息。 Yes Yes Yes Global Yes
innodb_ft_cache_size:当创建一个InnoDB FULLTEXT索引时在内存中存储已解析文档的缓存大小。 Yes Yes Yes Global No
innodb_ft_enable_diag_print:是否开启额外的全文搜索诊断输出。 Yes Yes Yes Global Yes
innodb_ft_enable_stopword:是否开启停止字。InnoDB FUllTEXT索引被创建时为其指定一个关联的停止字集。(若设置了innodb_ft_user_stopword_table则停止字由该选项指定的表获取,若没有设置innodb_ft_user_stopword_table而设置了innodb_ft_server_stopword_table则停止字由该选项指定的表获取,否则使用内置的停止字。) Yes Yes Yes Global Yes
innodb_ft_max_token_size:存储在InnoDB的FULLTEXT索引中的最大词长。设置这样一个限制后可通过忽略过长的关键字等有效降低索引大小从而加速查询。 Yes Yes Yes Global No
innodb_ft_min_token_size:存储在InnoDB的FULLTEXT索引中的最小词长。增加该值后会忽略掉一些通用的没有显著意义的词汇从而降低索引大小继而加速查询。 Yes Yes Yes Global No
innodb_ft_num_word_optimize:为InnoDB FULLTEXT索引执行OPTIMIZE操作每次所处理的词数。因为在含有全文搜索索引的表中执行批量的插入或更新操作需要大量的索引维护操作来合并所有的变化。因此,一般会运行一系列OPTIMIZE TABLE语句,每次从上一次的位置开始,处理指定数目的词,知道搜索索引被完全更新。 Yes Yes Yes Global Yes
innodb_ft_server_stopword_table:含有停止字的表,在创建InnoDB FULLTEXT索引时或忽略表中的停止字。停止字表需为InnoDB表,且在指定前应当已存在。 Yes Yes Yes Global Yes
innodb_ft_sort_pll_degree:为较大的表构建搜索索引时用于索引和记号化文本的并行线程数。 Yes Yes Yes Global No
innodb_ft_user_stopword_table:含有停止字的表,在创建InnoDB FULLTEXT索引时或忽略表中的停止字。停止字表需为InnoDB表,且在指定前应当已存在。 Yes Yes Yes Both Yes
innodb_optimize_fulltext_only:改变OPTIMIZE TABLE语句对InnoDB表操作的方式。 Yes Yes Yes Global Yes

4.全文搜索功能

全文搜索的语法:MATCH(col1,col2,…) AGAINST (expr[search_modifier])。其中MATCH中的内容为已建立FULLTEXT索引并要从中查找数据的列,AGAINST中的expr为要查找的文本内容,search_modifier为可选搜索类型。search_modifier的可能取值有:IN NATURAL LANGUAGEMODE、IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION、IN BOOLEAN MODE、WITH QUERY EXPANSION。search_modifier的每个取值代表一种类型的全文搜索,分别为自然语言全文搜索、带查询扩展的自然语言全文搜索、布尔全文搜索、查询扩展全文搜索(默认使用IN NATURAL LANGUAGE MODE)。

MySQL中全文索引的关键字为FULLTEXT,目前可对MyISAM表和InnoDB表的CHAR、VARCHAR、TEXT类型的列创建全文索引。全文索引同其他索引一样,可在创建表是由CREATE TABLE语句创建也可以在表创建之后用ALTER TABLE或者CREATE INDEX命令创建(对于要导入大量数据的表先导入数据再创建FULLTEXT索引比先创建索引后导入数据会更快)。

4.1自然语言全文搜索

自然语言全文搜索是MySQL全文搜索的默认搜索方式,实现从一个文本集合中搜索给定的字符串。这里,文本集合指的是指由FULLTEXT索引的一个或者多个列。

建表,并给title,body字段加FULLTEXT索引

导入数据

例1:

可以看到,语句查找到了包含指定内容的行。实际上,返回的行是按与所查找内容的相关度由高到低的顺序排列的。这个相关度的值由WHERE语句中的MATCH (…) AGAINST (…)计算所得,是一个非负浮点数。该值越大表明相应的行与所查找的内容越相关,0值表明不相关。该值基于行中的单词数、行中不重复的单词数、文本集合中总单词数以及含特定单词的行数计算得出。

例2:

由上例可知MATCH (…) AGAINST (…)实际上会计算一个相关值,可通过下例来验证。

可以看到,所得结果的第二列即为该行与查找内容的相关度。上例1中所得结果的顺序就是按此相关度排列的。

例3:

若想既看到查找到的结果又需要了解具体的相关度,可用下述方法达成。

可以看到,通过在查找部分和条件部分分别使用相同的MATCH(…) AGAINST(…)可以同时获取两方面的内容(不会增加额外开销,优化器知道两个MATCH(…) AGAINST(..)是相同的,只会执行一次该语句)

注意事项

默认情况下全文搜索大小写不敏感,如上例1,查找的内容为‘database’但含有‘DataBase’的行也会返回。可以通过为FULLTEXT索引列所使用的字符集指定一个特定的校对集来改变这种行为。

考虑下述两个SELECT语句:

这两条查询语句均可返回匹配的行数。但第一条语句可以利用基于WHERE从句的索引查找,因此在匹配的行数较少时速度较第二句更快。第二句执行了全表扫描,因此在匹配的行数较多时较第一句更快。

MATCH()函数中的列必须与FULLTEXT索引中的列相同。如MATCH(title,body)与FULLTEXT(title,body)。若要单独搜索某列,如body列,则需另外单独为该列建全文索引FULLTEXT(body),然后用MATCH(body)搜索。

对于InnoDB表MATCH()中的列仅能来自于同一个表,因为索引不能快多张表(MyISAM表的的布尔搜索因为可以不使用索引所以可以跨多张表中的列,但速度很慢)。

全文搜索不仅可以搜索类似例1中‘database’这样的单个的单词,还可以搜索句子(这才是其被称为‘全文搜索‘的关键),如例3。全文搜索把任何数字、字母、下划线序列看作是单词,还可以包含“’”如aaa’bbb备解析为一个单词,但aaa’’bbb备解析为两个单词,FULLTEXT解析器自动移除首尾的“’”,如’aaa’bbb’被解析为aaa’bbb。FULLTEXT解析器用“ ”(空格)、“,”(逗号)“.”(点号)作为默认的单词分隔符,因此对于不使用这些分隔符的语言如汉语来说FULLTEXT解析器不能正确的识别单词,对于这种情况需做额外处理。

全文搜索中一些单词会被忽略。首先是过短的单词,InnoDB全文搜索中默认为3个字符,MyISAM默认4个字符,可通过在创建FULLTEXT索引前改变配置参数来改变默认行为,对于InnoDB该参数为:innodb_ft_min_token_size,对于MyISAM为ft_min_word_len;另外stopword列表中的单词会被忽略。stopword列表包含诸如“the”、“or”、“and”等常用单词,这些词通常被认为没有什么语义价值。MySQL由内建的停止字列表,但是可以所使用自定义的停止字列表来覆盖默认列表。对于InnoDB控制停止字的配置参数为innodb_ft_enable_stopword,innodb_ft_server_stopword_table,  innodb_ft_user_stopword_table对于MyISAM参数为ft_stopword_file。

文本集合和查询语句中的单词的权重由该单词在集合或语句中的重要性确定。单词在越多的行中出现则该单词的权重越低,因为这表明其在文本集合中的语义价值较小。反之权重越高。例1中提到的相关度计算也与此值有关。

4.2布尔全文搜索

如果在AAGAINST()函数中指定了INBOOLEN MODE模式,则MySQL会执行布尔全文搜索。在该搜索模式下,待搜索单词前或后的一些特定字符会有特殊的含义。

例1:

该查询语句中“MySQL”前的“+”表明结果中必须包含“MySQL”而“YourSQL”前的“-”表明所得结果中不能含有“YourSQL”。

除了“+”和“-”外还有其他一些特定的字符。如空字符表明后跟的单词是可选的,但出现的话会增加该行的相关性;“@distance”用于指定两个或多个单词相互之间的距离(以单词度量)需在指定的范围内;“>”用于增加后跟单词对其所在行的相关性的贡献“<”用于降低该贡献;“()”用于将单词分组为子表达式且可以嵌套;“~”是后跟单词对其所在行的相关性的贡献值为负;“*”为普通的通配符,若为单词指定了通配符,那么即使该单词过短或者出现在了停止字列表中它也不会被移除;“””,括在双引号中的短语指明行必须在字面上包含指定的短语,全文搜索将短语分割为词后在FULLTEXT索引中搜索。非字字符无需完全匹配,如”test phrase”可以匹配含”test phrase”和”test phrase”的行,但匹配含”phrase test”的行。

例2:

找到包含MySQL或者YourSQL的行

例3:

找到包含同时MySQL和YourSQL的行

例4:

找到必须包含MySQl的行,YourSQL可有可无,但有YourSQL会增加相关性。

例5:

找到包含必须包含MySQL的行,YourSQL可有可无,若出现了YourSQL则会降低其所在行的相关性。

例6:

找到必须同时包含MySQL以及Security或Optimizing的行Security会增加所在行的相关性,而Optimizing会降低所在行的相关性。

例7:

找到包含da*的行。如包含DataBase、database等。

例8:

找到包含“MySQL Tutorial”短语的行。

布尔全文搜索的一些特点

  • MyISAM全文搜索会忽略至少在一半以上数据行中出现的单词(也即所谓的50%阈值),InnoDB无此限制。而在布尔全文搜索中MyISAM的50%阈值不生效。
  • 停止字列表也适用于布尔全文搜索。
  • 最小和最大词长全文搜索参数也适用于布尔全文搜索
  • MyISAM中的布尔搜索在FULLTEXT索引不存在的时候仍可工作,但速度很慢。而InnoDB表的各类全文搜索必须有FULLTEXT索引,否则会出现找不到与指定列相匹配的FULLTEXT索引的错误
  • InnoDB中的全文搜索不支持在单一搜索单词前使用多个操作符如“++MySQL”。MyISAM中全文搜索可以处理这种情况,但是会忽略除了紧邻单词之外的其他操作符。

4.3查询扩展全文搜索

某些时候我们通过全文搜索来查找包含某方面内容的行,比如我们搜索“database”,实际上我们期望返回结果不仅仅是仅包含“database”单词的行,一些包含“MySQL”、“SQLServer”、“Oracle”、“DB2”、“RDBMS”等的行也期望被返回。这个时候查询扩展全文搜索就能大显身手。

通过在AGAINST()函数中指定WITHQUERY EXPANSION 或者IN NATURAL MODE WITH QUERY EXPANSION可以开启查询扩展全文搜索模式。其工作原理是执行两次搜索,第一次用给定的短语搜索,第二次使用给定的短语结合第一次搜索返回结果中相关性非常高的一些行进行搜索。

例1:

使用自然语言搜索返回了包含“database”的行。

例2:

使用查询扩展全文搜索,不进返回了包含“database”的行,也返回了与例1中返回的行的内容相关的行。

注意事项

因为查询扩展会返回一些不相关的内容,因此会显著的引入噪声。索引仅当要查询的短语较短时才在考虑使用查询扩展全文搜索。

4.4全文搜索的停止字

上文已经简单介绍过了停止字列表,这里做详细介绍。停止字列表用MySQL Server所使用的字符集和校对集(分别由character_set_server和collation_server两个参数控制)载入并执行搜索。若用于全文索引和搜索的停止字文件或者停止字表使用了与MySQL Server不同的字符集和校对集会则导致查找停止字时错误的命中或未命中。

停止字查找的大小写敏感性也依赖于MySQL Server所使用的校对集,例如校对集为latin1_swedish_ci则查找是大小写不敏感的,若校对集为latin1_geberal_cs或者latin1_bin则查找是大小写敏感的。

InnoDB默认的停止字列表相对较短(因为技术上的或者文学等方面的文档常使用较短的词作为关键字或者有其他显著意义)。InnoDB默认的停止字列表存储在information_schema.innodb_ft_default_stopword表中。当然也可以通过自定义与innodb_ft_default_stopword表结构相同的表,填充期望的停止字,然后通过innodb_ft_server_stopword_table选项指定自定义的停止字表db_name/table_name,来改变默认的行为。另外还可以为innodb_ft_user_stopword_table选项指定含停止字的表,若同时指定了innodb_ft_default_stopword和innodb_ft_user_stopword_table则将使用后者指定的停止字表。上述操作改变所使用停止字表的操作需在创建全文索引前完成。且在指定所使用的停止字表时,表必须已经存在。

对于MyISAM可通过 ft_stopword_file选项指定所使用的停止字列表。MyISAM默认的停止字列表可在MySQL源码的 storage/myisam/ft_static.c文件中找到。

4.5全文搜索的限制

  • 目前只有InnoDB和MyISAM引擎支持全文搜索。其中InnodB表对FULLTEXT索引的支持从MySQL5.6.4开始。
  • 分区表不支持全文搜索。
  • 全文索引适用于多数多字节字符集。例外情况是:对于Unicode,utf8字符集可用但ucs2字符集不适用。尽管不能在ucs2列建立FULLTEXT索引,但可以在MyISAM表IN BOOLEAN MODE模式的搜索中搜索没有建立FULLTEXT索引的列。utf8的特性适用于utf8mb4,ucs2的特性适用于utf16、utf16e和utf32。
  • 表意型语言如汉语、日语没有诸如空格之类的单词定界符。因此FULLTEXT解析器不能确定此类语言中词的起止。对于此种情况要特殊处理(比如将中文转换成一种单字节类似英文习惯的存储方式)。
  • 允许在同一表中使用多种字符集,但FULLTEXT索引中的列必须使用同一字符集和校对集。
  • MATCH()函数中的列必须与FULLTEXT索引中定义的列完全一致,除非是在MyISAM表中使用IN BOOLEAN MODE模式的全文搜索(可在没有建立索引的列执行搜索,但速度很慢)。
  • AGAINST()函数中的参数需为在查询评估期间保持不变的字符串常量。
  • FULLTEXT搜索的索引提示比non-FULLTEXT搜索的索引提示要多一些限定:对于自然语言模式的全文搜索,索引提示会被忽略而不给出任何提示,比如虽明确在查询语句中给出了IGNORE INDEX(i)指明不使用i索引,但是该索引提示会被忽略掉,最终的查询中仍会使用索引i;对于布尔模式的全文搜索,FOR ORDER BY和FOR GROUP BY的索引提示会被忽略,FOR JOIN和不带FOR修饰符的索引提示不被忽略。

4.6全文搜索参数调整

仅有少量的用户可调参数用于调整MySQL的全文搜索能力。可以通过修改源码来获取更多对MySQL全文搜索行为的控制。但一般情况下不推荐这么做,除非很清楚自己在做什么,因为这些参数已经针对效率做过调整,修改默认的行为多数情况下反而会带来性能下降。

多数全文搜索相关的变量不能在Server运行的时候修改。需在Server启动时指定这些参数,或者修改完参数之后重新启动Server。另外,某些变量修改后需要重建FULLTEXT索引。

控制最小、最大字长的配置选项对于InnoDB为:innodb_ft_min_token_size和innodb_ft_max_token_size,对于MyISAM为:ft_min_word_len 和 ft_max_word_len。改变这些选项中任意一个的值都需重建FULLTEXT索引并重启Server。

用于停止字列表的配置选项对于InnoDB为:innodb_ft_enable_stopword、innodb_ft_server_stopword_table和innodb_ft_user_stopword_table,对于MyISAM为:ft_stopword_file。可以通过改变这些选项的值来开启/关闭停止字过滤并指定停止字列表。修改了这些选项后需重建索引并在必要的时候重启Server。

ft_stopword_file指定了包含停止字列表的文件,Server默认在数据目录搜索该文件除非用绝对路径指定了文件位置,若文件内容为空,则会关闭MyISAM的停止字过滤功能。停止字文件格式很灵活,可以使用任何非字母或数字的字符来界定停止字,但“_”和“’”例外,它们会被当作字的一部分处理。停止字列表使用Server默认的字符集。

MyISAM全文搜索的50%阈值特性可通过修改源码来关闭,将源码storage/myisam/ftdefs.h中的宏#define GWS_IN_USEGWS_PROB替换为#define GWS_IN_USE GWS_FREQ后重新编译MySQL即可。同样,不推荐上述方式,如果确实需要搜索一些通用的词,可以用布尔模式的全文搜获,此种情况下50%阈值特性不生效。

可以通过修改ft_boolean_syntax选项的值来更改MyISAM布尔全文搜做中默认使用的操作符(InnoDB无此选项)。该选项可动态改变但须超级用户权限,另外,改变了改制后无需重建FULLTEXT索引。

可以通过多种方式更改期望被认作是单词字符成分的字符集合。默认情况下“_”和“’”以及字母和数字被认为是组成单词的字符,其他的被默认为定界符。例如,我们现在想把连字符“-”也作为组成单词的字符处理,那么可以通过如下方式完成:

  • 修改MySQL源码,在storage/myisam/ftdefs.h文件中找到true_word_char()和misc_word_char()两个宏,在任一个宏定义里添加“-”,重新编译MySQL。
  • 修改字符集文件,true_word_char()宏实际上利用“character type”表来从其他字符中区分出字母和数字。可以通过编辑字符集对应的XML文件中<ctype><map>节点中的内容来将“-”指定为“字母“,然后将该字符集用于FULLTEXT索引。此种方式无需重新编译MySQL。对于编辑字符集XML文件,可参阅MySQL参考手册CharacterDefinition Arrays部分。
    http://dev.mysql.com/doc/refman/5.6/en/character-arrays.html
  • 对FULLTEXT索引列使用的字符集添加新的校对集,然后更新该列以使用新添加的校对集。具体参阅MySQL手册Adding a Collation to a Character Set以及Adding a Collation for Full-Text Indexing部分。
    http://dev.mysql.com/doc/refman/5.6/en/full-text-adding-collation.html
    http://dev.mysql.com/doc/refman/5.6/en/adding-collation.html

为InnoDB表重建FULLTEXT索引可以通过带DROP INDEX和ADD INDEX从句的ALTER TABLE语句完成,先删除旧的再创建新的。为MyISAM表重建FULLTEXT索引同样可通过上述语句完成,也可以通过QUICK repair操作来重建(但通常第一种方式会更快),如:

需要特别说明的是,若通过repair表的方式来为MyISAM表重建FULLTEXT索引,则通过上述语句进行即可。用myisamchk工具也可以为MyISAM表重建索引,但是容易导致查询产生错误的结果,对表的修改可能使Server认为该表被损坏了。究其原因是因为通过myisamchk工具执行修改MyISAM表的索引的操作时,除非明确指定了要使用的参数值否则使用默认的全文索引参数值(如最小最大词长等)重建FULLTEXT索引。导致这种情况是因为只有Server才知道这些全文索引参数值,MyISAM索引文件中不存储这些值。若更改过了这些值,如设置了ft_min_word_len=2,则在通过myisamchk工具修复表时要明确指定该修改过的参数值如:

当然也可以通过在MySQL配置文件[myisamchk]节中加入同[mysqld]节中与全文搜索相关参数一致的参数来确保myisamchk使用最新的参数值来重建表的FULLTEXT索引。

用myisamchk为MyISAM表修改索引的替代方式是使用REPAIR TABLE、ANALYZE TABLE、 OPTIMIZE TABLE、ALTER TABLE,这些语句是由Server执行的因此可以读取到正确的全文索引参数值,不会引起问题。

4.7为全文搜索添加校对字符集

参考

10.4. Adding a Collation to a Character Set

http://dev.mysql.com/doc/refman/5.6/en/adding-collation.html

12.9.7. Adding a Collation for Full-Text Indexing

http://dev.mysql.com/doc/refman/5.6/en/full-text-adding-collation.html

5.性能对比

词汇量:6个等级,分别用vocab01k、vocab05k、vocab10k、vocab15k,vocab25k、vocab35k标记,每个等级的词汇数如下,1000、5000、10000、15000、25000、35000。(取牛津词典单词部分,去重复后随机打乱顺序,分别截取前1000、5000、10000……作为对应的词汇量)

记录数:20个等级,分别用rec005k、rec010k、rec015k、rec020k、……rec095k、rec100k标记,每个等级的记录数如下,5000、10000、15000、20000、25000、30000、……、95000、100000。

根据词汇量等级和记录数等级分别生成含不同记录数且表中文本列是由对应的词汇量生成的随机文本的表,共6*20=120个。表的存储引擎使用InnoDB。表由id和body两个字段组成,分别为整型和文本型,且在body列创建了FULLTEXT索引。表名的命名规则为vocab01k_rec005k,表示该表中共含有5千条记录,每条记录中的body列由vocab01k对应的词汇量生成的随机单词组成,以此类推。每行记录中的body列定为由50个随机单词组成。

比较两类查询:LIKE从句查询以及使用FULLTEXT索引的MATCH()AGAINST()查询。在每个表上分别执行LIKE查询和MATCH() AGAINST()全文查询,每个表上的每个查询分别执行50次,记录每次所耗费的时间。对于每50个消耗的时间,删除其最大两个值和最小两个值,取剩余值的均值作为查询耗时的最终结果。这样一共可获得120*2 = 240个时间数据,根据这些数据绘图。在每个表上执行的查询如下(其中random_word1、random_word2、random_word3是根据查询时表对应的词汇量生成的随机单词。):

LIKE搜索:

FULLTEXT搜索:

5.3对比结果

LIKE搜索的耗时随着记录数的增加而线性增长,但对于10万行记录以下的表(这里共100000*50个单词)搜索时间基本上能保持在1秒以内,所以like搜索的性能也不是特别差。由不同词汇量生成的文本对LIKE搜索的性能影响不大,不同词汇量对应的搜索时间基本上在一个很小的时间范围内变化。

FULLTEXT搜索耗时也随表中记录数的增长而线性增加。对于10万行记录以下的表(这里共100000*50个单词)搜索时间基本上能保持在0.01秒以内。由不同词汇量生成的随机文本对FULLTEXT搜索性能有相对来说比较显著的影响。每行记录中含同样的单词数,这样,较大的词汇量倾向于生成冗余度更低的文本,相应的搜索耗时倾向于更少。这可能与FULLTEXT索引建立单词索引的机制有关,较大的词汇量倾向于生成范围广但相对较浅的索引,因而能快速确定文本是否匹配。

与LIKE搜索相比,FULLTEXT全文搜索的性能要强很多,对于10万行记录的表,搜索时间都在0.02秒以下。因此可以将基于FULLTEXT索引的文本搜索部署于网站项目中的文本搜索功能中。但是,正如上述提到的,无论是LIKE搜索还是FULLTEXT搜索,其性能都会随着记录数的增长而下降,因此,若网站项目中的文本搜索数据库记录数庞大的一定规模后,可能需要考虑使用MySQL数据库全文搜索以外的文本搜索解决方案了。

0

Java 随机数生成 Random 种子(seed)的作用

不同的构造函数

Random 通常用来作为随机数生成器,它有两个构造方法:

1.不含参构造方法:

2.含参构造方法:

都调用的 setSeed 方法:

可以看到,不含参构造方法每次都使用当前时间作为种子,而含参构造方法是以一个固定值作为种子。

什么是种子 seed 呢?

seed 是 Random 生成随机数时使用的参数:

Random 中最重要的就是 next(int) 方法,使用 seed 进行计算:

其他 nextXXX 方法都是调用的 next()。

比如 nextInt(int):

再比如 nextBoolean():

举个栗子:

分别用含参构造方法和不含参构造方法创建 5 个随机生成器对象,每个随机生成器再生产 8 个随机数,对比下结果:

 

再运行一次:


总结:

通过上述例子可以发现:

随机数是种子经过计算生成的。

不含参的构造函数每次都使用当前时间作为种子,随机性更强
而含参的构造函数其实是伪随机,更有可预见性

0

Java nanoTime 与 currentTimeMillis 比较

System.nanoTime与System.currentTimeMillis比较

currentTimeMillis返回的是系统当前时间和1970-01-01之前间隔时间的毫秒数,如果系统时间固定则方法返回值也是一定的(这么说是为了强调和nanoTime的区别),精确度是毫秒级别的。

nanoTime的返回值本身则没有什么意义,因为它基于的时间点是随机的,甚至可能是一个未来的时间,所以返回值可能为负数。但是其精确度为纳秒,相对高了不少。

currentTimeMillis不仅可以用来计算代码执行消耗的时间 ,也可以和Date类方便的转换。而nanoTime则不行。

可以这么说吧,currentTimeMillis是一个时钟,而nanoTime是一个计时器,你可以用时钟来计算时间差,也可以用来单纯的看时间,但是作为计时器的nanoTime则只能用来计算时间差,好在优点是精确度高。

currentTimeMillis是基于系统时间的,也就是说如果你在程序执行期间更改了系统时间则结果就会出错,而nanoTime是基于CPU的时间片来计算时间的,无法人为干扰
前面说了nanoTime基于的时间点是随机的,但是对于同一个JVM里,不同地方使用到的基点时间是一样的。

代码比较

 

总结如下:

1.currentTimeMillis精度上相对于nanoTime要输很多
2.nanoTime方法本身执行的时间相对于currentTimeMillis要多很多,所以应当只在精确度要求较高时使用nanoTime
3.currentTimeMillis是时钟,nanoTime是计时器

0

Java Collections.emptyList() 方法的使用及注意事项

Java Collections.emptyList方法的使用及注意事项

一、emptyList()

作用:

返回一个空的List(使用前提是不会再对返回的list进行增加和删除操作);

好处:

1. new ArrayList()创建时有初始大小,占用内存,emptyList()不用创建一个新的对象,可以减少内存开销;
2. 方法返回一个emptyList()时,不会报空指针异常,如果直接返回Null,没有进行非空判断就会报空指针异常;

注意:此List与常用的List不同,它是Collections类里的静态内部类,在继承AbstractList后并没有实现add()、remove()等方法,所以返回的List不能进行增加和删除元素操作。

示例:

增删操作:

结果:

Java Collections.emptyList() 方法的使用及注意事项

如果需要对collections.emptyList()进行增删操作的话,就需要将collections.emptyList()转换成ArrayList()进行操作。

示例:

结果:

Java Collections.emptyList() 方法的使用及注意事项

0

JAVA8 ConcurrentHashMap.computeIfAbsent 的使用及说明

1.简述

在JAVA8的Map接口中,增加了一个方法computeIfAbsent:

如果mappingFunction(key)返回的值为null或抛出异常,则不会有记录存入map
此方法首先判断缓存MAP中是否存在指定key的值,如果不存在,会自动调用mappingFunction(key)计算key的value,然后将key = value放入到缓存Map。

ConcurrentHashMap中重写了computeIfAbsent 方法确保mappingFunction中的操作是线程安全的。

2.使用方法

可以将原始代码为:

使用computeIfAbsent 代替:

注:mappingFunction方法的结果会作为值直接插入到map中,无需在mappingFunction中再执行put。

3.风险

不能在ConcurrentHashMap.computeIfAbsent方法中进行递归调用,及在mappingFunction方法中不能在进行put相关的操作会造成死循环。

例如:

This is fixed in JDK 9 with JDK-8071667 . When the test case is run in JDK 9-ea, it gives a ConcurrentModification Exception.
https://bugs.openjdk.java.net/browse/JDK-8172951
好在这个问题在java 1.9中已经基本修复了。

0