问题1:////////////////////////////////////////公司目前有一个需求在10W左右的数据上  对一字段(varchar) 实现 :模糊快速 检索。说下我目前做的一些实验(没用过Oracle,但是请大家给点意见,数据库的原理都差不多!):mysql5:对该 字段 建立索引:  查询  like  '%NNN'      在java程序上用时  50ms(毫秒)左右 sql2000:对该 字段 建立索引:  查询  like  '%NNN'    在java程序上用时  40ms左右         对该 字段 建立全文索引:可以实现模糊查询    在java程序上用时  100ms左右 lucene : 对该 字段 建立索引(并保存所有数据)  可以实现模糊查询    在java程序上用时  170ms左右 
领导说效率太低了:领导希望在 该数据量(10W+)下模糊查询:10ms以下 模糊查询的定义:  如:  输入  “北京 + 空格 + 商场”  把包含  北京  和 商场  (北京 和 商场 的位置可前可后——可互换位置) 的数据都查出:(4)  如果将 北京  和 商场 给索引了(2列数据)  怎么查出  都包含 北京和商场的对应数据
领导给我一个建议(索引表——我不了解是什么):他给我解释是: 先将 该字段  分词  建立一个表(table2) ,再在table2上做索引,然后再搜索。我是一个才毕业的学生,因为水平有限,请各位前辈都给点指点和意见!您的回答:1:10W+数据量下 10ms以下 的模糊查询(如上解释)是否能否实现?2:如果1能实现,实现的方法是?(如果能够自信请仔细点)3:其他方法建议(可能提高数据检索的速度和实现模糊查询功能)!!!4:(4如上标注)怎么实现?希望各位前辈和朋友不吝赐教!不会的朋友也可以学学数据检索方面的知识。来给意见和回答的朋友都给分,分不够则加。。希望都来说一下!!我都弄了2个星期了,还是没什么眉目!!再次谢谢 各位了!! 问题1结束////////////////////////////////////////////////////
问题2:///////////////////////////////////////////////////////////
现在的状态:
原始数据表(dataTable)  27000+的数据
目前我又前进了一点了,我先用一个分词器,将该表中的该字段给做了 分词,然后将分词后的内容存入 table2(keyName{单个词元},strId)在 keyName上做了索引,strId是 类似 12,45,365,789 用逗号分隔的id的字符串,就是将含有keyName词元的dataTable的id字段保存进来到时候搜索的时候就  select * from table2 where keyName in('北京','商场');然后程序判断,strid取出来做匹配,有相同id的取出来,再到dataTable取,
目前速度大概是20ms,最快10ms(但是可能性很小,1%不到) (查询用时 是在java程序中println出来的,在数据库中不知道怎么查看精确到ms的查询时间)今天给领导看了,说还不行,说效率还可以提高10倍左右(大概也就是2ms?)我现在已经不知道还要怎么做了(他说在table2上在做索引)!(这个再做索引,该怎么弄下去啊?):请各位给点再优化的方法或者意见!问题2结束//////////////////////////////////////////////////////////各位,我知道我说的不是很清楚,!有什么不清楚的地方请直言!以上2个问题随便回答一个都可以!希望能够得到帮助!

解决方案 »

  1.   

    就速度来说,只要机器足够好,多少ms都能达到....
    oracle有全文索引的(网上一搜一大堆),能快到多少不好说,试了才知道....
      

  2.   

    关于不确定位置的模糊查询,几个较大数据库产品应该都有自己的解决方式的.
    oracle的话,可以采用全文索引,网上自己找一下资料.
      

  3.   


    strId 就单单存取id字段就可以了。可以这样子
    table2
    keyName strid
    北京    12
    北京    45
    北京    369
    再在keyname,和strid建索引同时datable.id也建索引
    查找的时候直接
    select * from datatable,table2 where table2.keyname='xx' and table2.strid=datatable.id;
      

  4.   


    确实如此,而你那样写like貌似用不到索引,只有类似 like 'XXX%'才能用到(没记错的话)
    当然你的需求也不适合用like,你不确定关键字的顺序,
    你可以用instr(字段,'关键字')>0试试,这是oracle的,sql server里是charindex.
    我也是新人,只知道这么多了,等高手吧.
      

  5.   


    谢谢你,但是我还有的要求就是  keyname='xx'   or keyname='yy'  or keyName='bb' 这些都有可能,不是一个条件,因为要分词,再匹配,
    我目前做的就是   反向索引   http://zhangyu8374.javaeye.com/blog/86307  大概就是这个样子!
      

  6.   

    LZ把你具体的的查询条件说说。
    ORACLE中的反向索引主要是为了消除热块。
      

  7.   


    还有我不是用的 oracle的反向索引  基本是
    http://zhangyu8374.javaeye.com/blog/86307  中的方式1:
      

  8.   

    多个也可以那样存储啊 。比如
    xx 12
    xx 52
    xx 65
    yy 54
    yy 65
    这样子阿,我觉得你用逗号隔开再解析这步是不必要的
      

  9.   

    在oracle中,like '%xxx'是不能用索引的。
    我的意思是如果不用全文检索,又不分表,那么就只有下面这样用的上索引。OPER@tl> select * from test;AAA                                                                 BBB
    ------------------------------------------------------------ ----------
    北京多方式                                                            1
    打扫可达                                                              2
    商场四大                                                              3
    但是商场后台                                                          4
    单北京当商场的                                                        5
    人商场的北京                                                          6
    人商的的北京                                                          7已选择7行。OPER@tl> create index ind_test on test(instr(aaa,'北京'));索引已创建。OPER@tl> create index ind_test2 on test(instr(aaa,'商场'));索引已创建。OPER@tl> exec dbms_stats.gather_table_stats('OPER','TEST',cascade=>true)PL/SQL 过程已成功完成。OPER@tl> set autot on
    OPER@tl> select * from test
      2  where instr(aaa,'商场')>0
      3  and instr(aaa,'北京')>0;AAA                                                                 BBB
    ------------------------------------------------------------ ----------
    单北京当商场的                                                        5
    人商场的北京                                                          6
    执行计划
    ----------------------------------------------------------
    Plan hash value: 3856466897----------------------------------------------------------------------------------------
    | Id  | Operation                   | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT            |          |     4 |    84 |     2   (0)| 00:00:01 |
    |*  1 |  TABLE ACCESS BY INDEX ROWID| TEST     |     4 |    84 |     2   (0)| 00:00:01 |
    |*  2 |   INDEX RANGE SCAN          | IND_TEST |     5 |       |     1   (0)| 00:00:01 |
    ----------------------------------------------------------------------------------------Predicate Information (identified by operation id):
    ---------------------------------------------------   1 - filter(INSTR("AAA",'商场')>0)
       2 - access(INSTR("AAA",'北京')>0)
    统计信息
    ----------------------------------------------------------
              1  recursive calls
              0  db block gets
              4  consistent gets
              0  physical reads
              0  redo size
            547  bytes sent via SQL*Net to client
            400  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
              2  rows processedOPER@tl> 
      

  10.   


    谢谢您的帮助!我知道了!!  比如说我目前的状态(分词后在table2中建立了反向索引了,还有什么其他的优化办法没?我们领导说再在table2上索引——我不知道怎么做!)
      

  11.   

    比如我原始数据表:dataTable
    id   name
    1   艾林商场(内江)
    2   奥兰多购物中心(乐山)
    3   长城购物中心(资阳)
    4   长兴百货商场(绵阳)
    5   成都百货商场都江堰店
    6   成都人民商场(泸州)反向索引表 table2()
    keyname    strid
    "内江",   "1,11,"
    "奥兰",   "2,2,11603,2"
    "多",     "2,2,11571,11603,11694,11729"
    "中心",   "2,3,13,23,25,31,37,47,98,102"
    "乐山",   "2,10,15,16,20,21,220,"
    "资阳",   "3,14,43,155,460,758,759,8"
    "长兴",   "4,4,6132,6133,7804,8645,10953,25693,4"
    "百货",   "4,5,12,18,24,29,38,40,41,42,43,44"
    ………………table2 再索引??
      

  12.   

    table2 再索引??  有意义吗
      

  13.   

    你用的DBMS不是ORACLE,不清楚你的反向索引的意义。
    你能用我说的那种方式建立索引以及查询吗?
      

  14.   

    应该不行吧。!
    我们公司数据库不是用的oracle,
    只能是mysql 和 sql中的一个1
      

  15.   


    楼主怎么做的分词?我很感兴趣。像你上面的这种格式,应该把strid做成原子的:
    keyname strid
    内江       1
    内江       11这样可以在keyname上建个索引之类的,然后查起来就快了
      

  16.   


    网络上找的一个分词组件,paoding啊这些都可以!这样可以在keyname上建个索引之类的,然后查起来就快了?   (我现在的keyname上已经做了索引了)
      

  17.   

    26楼,我觉得如果像这样的数据表结构keyname strid
    内江      1
    内江      11 是不是会带来数据检索上的性能损耗,而且,如果是这样的数据结构,我需要查找多关键字的话,就需要在 java程序中执行多条select 语句,我觉得还是保存在一起,然后取出来了。每个 ResultSet(结果集) 在判断strid中的每个id是否有相同的(取 交集)
      

  18.   

    (题外话:你们领导以前是做什么的?做搜索的?)
    随便说个10ms就让你去实现,10ms和2ms的要求从哪里来,有没有什么依据?
    如果没有依据的话,那么你的试验结果就是最好的依据了。注意,SQL语句里面的 '%A%B%' 是和顺序有关的,这个条件搜索结果和 '%B%A%' 是不一样的。
    而且 like '%A%B%' 这样的语句,很多时候根本无法使用索引,所以快不起来。你们领导说的分词,再建索引表那些东西,其实和lucene建索引时很相似,但lucene是用倒排表
    如果要在数据库里面实现这些东西,还不如考虑使用lucene呢另外,你可以考虑使用数据库本身的全文索引功能,这不完全是针对大文本的。
      

  19.   

    你有这样的领导真好啊,兄弟这样你才能提高技术啊,正在研究lucene.....