IndexWriter
Hibernate的SessionFactory
在Hibernate中,一般保持一个数据库就只有一个SessionFactory。因为在SessionFactory中维护二级缓存,而SessionFactory又是线程安全的。所以SessionFactory是共享的。
lucene的IndexWriter
如果同时在一个索引库中同时建立两个IndexWriter,例如:
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
IndexWriter indexWriter = new IndexWriter(LuceneUtils.directory,LuceneUtils.analyzer,MaxFieldLength.LIMITED);
IndexWriter indexWriter2 = new IndexWriter(LuceneUtils.directory,LuceneUtils.analyzer,MaxFieldLength.LIMITED);
这样的代码会出现异常
而lucene的目录结构:
.会出现write.lock这个文件。因为当一个IndexWriter在进行读索引库操作的时候,lucene会为索引库,以防止其他IndexWriter访问索引库而导致数据不一致,直到IndexWriter关闭为止。
结论:同一个索引库只能有一个IndexWriter进行操作。
封装IndexWriter的类LuceneIndexWriter
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
public class LuceneIndexWriter {
private static IndexWriter indexWriter = null;
public static IndexWriter getIndexWriter() {
if (indexWriter == null) {
try {
indexWriter = new IndexWriter(LuceneUtils.directory,
LuceneUtils.analyzer, MaxFieldLength.LIMITED);
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return indexWriter;
}
public static void close() {
if (indexWriter != null) {
try {
indexWriter.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println("indexWriter为空,不能关闭!");
}
}
}
注:这里用单例模式做比较好。
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
/**
* 1、索引库的增、删、改是由indexWriter来操作的
* 2、同一个时刻内,同一个索引库,只能允许一个indexWriter操作
* 3、当IndexWriter创建完成以后,indexwriter所指向的索引库就被占领了,只有当indexWriter.close时,才能释放锁的资源
* 4、当一个新的indexWriter想拥有索引库时,原来的indexWriter必须释放锁
* 5、只要索引库中存在write.lock文件,说明上锁了
* 6、indexWriter.close有两层含义:
* * 关闭IO资源
* * 释放锁
* @author Administrator
*
*/
public class IndexWriterTest {
@Test
public void testIndexWriter() throws Exception{
IndexWriter indexWriter = new IndexWriter(LuceneUtils.directory,LuceneUtils.analyzer,MaxFieldLength.LIMITED);
indexWriter.close();
IndexWriter indexWriter2 = new IndexWriter(LuceneUtils.directory,LuceneUtils.analyzer,MaxFieldLength.LIMITED);
}
}
索引库的优化
1.设置索引库文件合并
当执行创建索引多次时,索引库的文件如图所示:(索引里内容是一样的)
从图中可以看出来,每执行一次就生成一个cfs文件。当执行delete操作时,会生成如图所示的结构:
从图中可以看出来,lucene在执行删除的时候,是先把要删除的元素形成了一个文件del文件,然后再和cfs文件进行整合得出最后结果。
结论:如果增加、删除反复操作很多次,就会造成文件大量增加,这样检索的速度也会下降,所以我们有必要去优化索引结构。使文件的结构发 生改变从而提高效率。
手动合并文件
合并多个小文件为一个大文件,减少IO操作:
在indexWriter.close();前加上
indexWriter.optimize();
即可
在执行完上述代码后,索引库的结构为:
可以看出把该合并的项都合并了。把del文件彻底全部删除掉了。
自动合并文件(设置合并因子)
indexWriter.setMergeFactor(3);
当cfs文件的数量为3个时,这是会自动合并成一个文件。
如果没有设置数量,默认情况下为10;
2.将索引数据进行分区
3.将第一次查询数据时将索引读到内存中,以后再读取时就可以从内存中获取,不用再从硬盘中获取
代码实现
public void testOptimise4() throws IOException, ParseException{
//索引在硬盘里面...
Directory directory1=FSDirectory.open(new File(Contants.INDEXURL));
IOContext ioContext=new IOContext();
//索引放在内存当中...
Directory directory=new RAMDirectory(directory1,ioContext);
IndexReader indexReader=DirectoryReader.open(directory);
IndexSearcher indexSearcher=new IndexSearcher(indexReader);
String fields []={"title"};
QueryParser queryParser=new MultiFieldQueryParser(LuceneUtils.getMatchVersion(),fields,LuceneUtils.getAnalyzer());
//不同的规则构造不同的子类..
//title:keywords ,content:keywords
Query query=queryParser.parse("抑郁症");
TopDocs topDocs=indexSearcher.search(query, 100);
System.out.println(topDocs.totalHits);
}
4.排除停用词,排除停用没被分词器过滤掉,词就不会建立索引,索引文件就会变小,这样 收索的时候就会变快。。
5.通过查询条件优化
Hibernate的SessionFactory
在Hibernate中,一般保持一个数据库就只有一个SessionFactory。因为在SessionFactory中维护二级缓存,而SessionFactory又是线程安全的。所以SessionFactory是共享的。
lucene的IndexWriter
如果同时在一个索引库中同时建立两个IndexWriter,例如:
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
IndexWriter indexWriter = new IndexWriter(LuceneUtils.directory,LuceneUtils.analyzer,MaxFieldLength.LIMITED);
IndexWriter indexWriter2 = new IndexWriter(LuceneUtils.directory,LuceneUtils.analyzer,MaxFieldLength.LIMITED);
这样的代码会出现异常
而lucene的目录结构:
.会出现write.lock这个文件。因为当一个IndexWriter在进行读索引库操作的时候,lucene会为索引库,以防止其他IndexWriter访问索引库而导致数据不一致,直到IndexWriter关闭为止。
结论:同一个索引库只能有一个IndexWriter进行操作。
封装IndexWriter的类LuceneIndexWriter
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
public class LuceneIndexWriter {
private static IndexWriter indexWriter = null;
public static IndexWriter getIndexWriter() {
if (indexWriter == null) {
try {
indexWriter = new IndexWriter(LuceneUtils.directory,
LuceneUtils.analyzer, MaxFieldLength.LIMITED);
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return indexWriter;
}
public static void close() {
if (indexWriter != null) {
try {
indexWriter.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println("indexWriter为空,不能关闭!");
}
}
}
注:这里用单例模式做比较好。
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
/**
* 1、索引库的增、删、改是由indexWriter来操作的
* 2、同一个时刻内,同一个索引库,只能允许一个indexWriter操作
* 3、当IndexWriter创建完成以后,indexwriter所指向的索引库就被占领了,只有当indexWriter.close时,才能释放锁的资源
* 4、当一个新的indexWriter想拥有索引库时,原来的indexWriter必须释放锁
* 5、只要索引库中存在write.lock文件,说明上锁了
* 6、indexWriter.close有两层含义:
* * 关闭IO资源
* * 释放锁
* @author Administrator
*
*/
public class IndexWriterTest {
@Test
public void testIndexWriter() throws Exception{
IndexWriter indexWriter = new IndexWriter(LuceneUtils.directory,LuceneUtils.analyzer,MaxFieldLength.LIMITED);
indexWriter.close();
IndexWriter indexWriter2 = new IndexWriter(LuceneUtils.directory,LuceneUtils.analyzer,MaxFieldLength.LIMITED);
}
}
索引库的优化
1.设置索引库文件合并
当执行创建索引多次时,索引库的文件如图所示:(索引里内容是一样的)
从图中可以看出来,每执行一次就生成一个cfs文件。当执行delete操作时,会生成如图所示的结构:
从图中可以看出来,lucene在执行删除的时候,是先把要删除的元素形成了一个文件del文件,然后再和cfs文件进行整合得出最后结果。
结论:如果增加、删除反复操作很多次,就会造成文件大量增加,这样检索的速度也会下降,所以我们有必要去优化索引结构。使文件的结构发 生改变从而提高效率。
手动合并文件
合并多个小文件为一个大文件,减少IO操作:
在indexWriter.close();前加上
indexWriter.optimize();
即可
在执行完上述代码后,索引库的结构为:
可以看出把该合并的项都合并了。把del文件彻底全部删除掉了。
自动合并文件(设置合并因子)
indexWriter.setMergeFactor(3);
当cfs文件的数量为3个时,这是会自动合并成一个文件。
如果没有设置数量,默认情况下为10;
2.将索引数据进行分区
3.将第一次查询数据时将索引读到内存中,以后再读取时就可以从内存中获取,不用再从硬盘中获取
代码实现
public void testOptimise4() throws IOException, ParseException{
//索引在硬盘里面...
Directory directory1=FSDirectory.open(new File(Contants.INDEXURL));
IOContext ioContext=new IOContext();
//索引放在内存当中...
Directory directory=new RAMDirectory(directory1,ioContext);
IndexReader indexReader=DirectoryReader.open(directory);
IndexSearcher indexSearcher=new IndexSearcher(indexReader);
String fields []={"title"};
QueryParser queryParser=new MultiFieldQueryParser(LuceneUtils.getMatchVersion(),fields,LuceneUtils.getAnalyzer());
//不同的规则构造不同的子类..
//title:keywords ,content:keywords
Query query=queryParser.parse("抑郁症");
TopDocs topDocs=indexSearcher.search(query, 100);
System.out.println(topDocs.totalHits);
}
4.排除停用词,排除停用没被分词器过滤掉,词就不会建立索引,索引文件就会变小,这样 收索的时候就会变快。。
5.通过查询条件优化