Skip to content


Sphinx搜索语法

参考:http://www.coreseek.com/uploads/pdf/sphinx_doc_zhcn_0.9.pdf

1.匹配模式
有如下可选的匹配模式:

  • SPH_MATCH_ALL, 匹配所有查询词(默认模式)
  • SPH_MATCH_ANY, 匹配查询词中的任意一个
  • SPH_MATCH_PHRASE, 将整个查询看作一个词组,要求按顺序完整匹配
  • SPH_MATCH_BOOLEAN, 将查询看作一个布尔表达式
  • SPH_MATCH_EXTENDED, 将查询看作一个Sphinx内部查询语言的表达式

还有一个特殊的“完整扫描”模式,当如下条件满足时,该模式被自动激活:

1. 查询串是空的(即长度为零)
2. docinfo 存储方式为extern
在完整扫描模式中,全部已索引的文档都被看作是匹配的。这类匹配仍然会被过滤、排序或
分组,但是并不会做任何真正的全文检索。这种模式可以用来统一全文检索和非全文检索的
代码,或者减轻SQL服务器的负担(有些时候Sphinx扫描的速度要优于类似的MySQL查
询)

2. 布尔查询
布尔查询允许使用下列特殊操作符:
 显式的与(AND)操作符
hello & world
 或(OR)操作符
hello | world
 非(NOT)操作符
hello -world
hello !world
 分组(grouping)
( hello world )
以下是一个使用了如上全部操作符的例子:

布尔查询示例
( cat -dog ) | ( cat -mouse)

与(AND)操作符为默认操作,所以“hello world”其实就是“hello & world”
或(OR)操作符的优先级高于与操作符,因此“lookingfor cat | dog | mouse”意思是”looking for (
cat | dog | mouse )” 而不是 “(looking for cat) | dog | mouse”
像“-dog”这种查询不能被执行,因为它差不多包括索引所有文档。这既有技术上的原因,
也有性能上的原因。从技术上说,Sphinx并不总是保持一个全部文档ID的列表。性能方面,
当文档集非常大的时候(即10-100M个文档),对这种执行查询可能需要很长的时间。

3. 扩展查询
在扩展查询模式中可以使用如下特殊操作符:
 或(OR)操作符
hello | world
 非(NOT)操作符
hello -world
hello !world
 字段(field)搜索符:
@title hello @body world
 词组搜索符
“hello world”
 近似搜索符
“hello world”~10
 阀值匹配符
“the world is a wonderful place”/3
下例使用了上述大多数操作符:

扩展查询示例
“hello world” @title “example program”~5 @body python -(php|perl)
与(AND)操作为默认操作,因此“hello world”意思是“hello”和“world”必须同时存在文档才
能匹配。
或(OR)操作符的优先级要高于与操作符,因此”looking for cat | dog | mouse” 意思
是”looking for ( cat | dog | mouse )” 而不是”(looking for cat) | dog | mouse”;
近似距离以词为单位,随词数变化而变化,并应用于引号中的全部词。举个例子,”cat dog
mouse”~5 这个查询的意思是必须有一个少于8个词的词串,它要包含全部的三个词,也就
是说”CAT aaa bbb ccc DOG eee fff MOUSE” 这个文档不会匹配这个查询,因为这个词串正好
是8个词。
阀值匹配符引入了一种模糊匹配。它允许至少含有某个阈值数量个匹配词的文档通过。上述
例子(”the world is a wonderful place”/3)会匹配含有指定的六个词中的至少三个的那些文档。
类似如下查询中嵌套的括号
aaa | ( bbb ccc | ( ddd eee ) )
目前还是不允许的,但是这会在今后得以改进。
取否(也就是非(NOT)操作符)只允许用在最外一层且不能在括号(也就是分组)里。这
个特性不会改变,因为支持嵌套的非操作会大大提高词组相关度计算实现的复杂性。

4. 权值计算
采用何种权值计算函数(目前)取决于查询的模式。
There are these major parts which are used in the weighting functions:
权值计算函数进行如下两部分主要部分:
1. 词组评分
2. 统计学评分
词组评分根据文档和查询的最长公共子串(LCS,longest common subsequence)的长度进行。
因此如果文档对查询词组有一个精确匹配(即文档直接包含该词组),那么它的词组评分就
取得了可能的最大值,也就是查询中词的个数。
统计学评分基于经典的BM25函数,该函数仅考虑词频。如果某词在整个数据库中很少见
(即文档集上的低频词)或者在某个特定文档中被经常提及(即特定文档上的高频词),那
么它就得到一个较高的权重。最终的BM25权值是一个0到1之间的浮点数。
在所有模式中,数据字段的词组评分是LCS乘以用户指定的数据字段权值。数据字段权值
是整数,默认为1,且字段的权值必须不小于1。
在SPH_MATCH_BOOLEAN模式中,不做任何权重估计,每一个匹配项的权重都是1。
在SPH_MATCH_ALL和SPH_MATCH_PHRASE模式中,最终的权值是词组评分的加权和。
在SPH_MATCH_ANY模式中,于前面述两模式的基本思想类似,只是每个数据字段的权重
都再加上一个匹配词数目。在那之前,带权的词组相关度被额外乘以一个足够大的数,以便
确保任何一个有较大词组评分的数据字段都会使整个匹配的相关度较高,即使该数据字段的
权重比较低。
在SPH_MATCH_EXTENDED模式中,最终的权值是带权的词组评分和BM25权重的和,再
乘以1000并四舍五入到整数。
这个行为将会被修改,以便使MATCH_ALL和MATCH_ANY这两个模式也能使用BM25算
法。这将使词组评分相同的搜索结果片断得到改进,这在只有一个词的查询中尤其有用。
关键的思想(对于除布尔模式以外的全部模式中)是子词组的匹配越好则评分越高,精确匹
配(匹配整个词组)评分最高。作者的经验是,这种基于词组相似性的评分方法可以提供比
任何单纯的统计模型(比如其他搜索引擎中广泛使用的BM25)明显更高的搜索质量。

5. 排序模式
可使用如下模式对搜索结果排序:
 SPH_SORT_RELEVANCE 模式, 按相关度降序排列(最好的匹配排在最前面)
 SPH_SORT_ATTR_DESC 模式, 按属性降序排列 (属性值越大的越是排在前面)
 SPH_SORT_ATTR_ASC模式, 按属性升序排列(属性值越小的越是排在前面)
 SPH_SORT_TIME_SEGMENTS 模式, 先按时间段(最近一小时/天/周/月)降序,再按
相关度降序
 SPH_SORT_EXTENDED 模式, 按一种类似SQL的方式将列组合起来,升序或降序排
列。
 SPH_SORT_EXPR 模式,按某个算术表达式排序。
SPH_SORT_RELEVANCE忽略任何附加的参数,永远按相关度评分排序。所有其余的模式
都要求额外的排序子句,子句的语法跟具体的模式有关。SPH_SORT_ATTR_ASC,
SPH_SORT_ATTR_DESC以及SPH_SORT_TIME_SEGMENTS这三个模式仅要求一个属性名。
SPH_SORT_RELEVANCE模式等价于在扩展模式中按”@weight DESC, @id ASC”排序,
SPH_SORT_ATTR_ASC 模式等价于”attribute ASC, @weight DESC, @id ASC”,而
SPH_SORT_ATTR_DESC 等价于”attribute DESC, @weight DESC, @id ASC”。
SPH_SORT_TIME_SEGMENTS模式
在SPH_SORT_TIME_SEGMENTS模式中,属性值被分割成“时间段”,然后先按时间段排
序,再按相关度排序。
时间段是根据搜索发生时的当前时间戳计算的,因此结果随时间而变化。所说的时间段有如
下这些值:
 最近一小时
 最近一天
 最近一星期
 最近一个月
 最近三个月
 其他值
时间段的分法固化在搜索程序中了,但如果需要,也可以比较容易地改变(需要修改源码)。
这种模式是为了方便对Blog日志和新闻提要等的搜索而增加的。使用这个模式时,处于更
近时间段的记录会排在前面,但是在同一时间段中的记录又根据相关度排序-这不同于单纯
按时间戳排序而不考虑相关度。
SPH_SORT_EXTENDED 模式
在 SPH_SORT_EXTENDED 模式中,您可以指定一个类似SQL的排序表达式,但涉及的属
性(包括内部属性)不能超过5个,例如:
@relevance DESC, price ASC, @id DESC
只要做了相关设置,不管是内部属性(引擎动态计算出来的那些属性)还是用户定义的属性
就都可以使用。内部属性的名字必须用特殊符号@开头,用户属性按原样使用就行了。在上
面的例子里,@relevance和@id是内部属性,而price是用户定义属性。
已知的内部属性:
 @id (match ID)
 @weight (match weight)
 @rank (match weight)
 @relevance (match weight)
 @id(匹配的ID)
 @weight(匹配权值)
 @rank(匹配权值)
 @relevance(匹配权值)
@rank和@relevance只是@weight的额外别名。
SPH_SORT_EXPR 模式
表达式排序模式使您可以对匹配项按任何算术表达式排序,表达式中的项可以是属性值,内
部属性(@id和@weight),算术运算符和一些内建的函数。例如:
$cl->SetSortMode ( SPH_SORT_EXPR,
“@weight + ( user_karma + ln(pageviews) )*0.1” );
支持的运算符和函数如下。它们是模仿MySQL设计的。函数接受参数,参数的数目根据具
体函数的不同而不同。
 Operators: +, -, *, /, <, > <=, >=, =, <>.
 Unary (1-argument) functions: abs(), ceil(), floor(), sin(), cos(), ln(), log2(), log10(), exp(),
sqrt().
 Binary (2-argument) functions: min(), max(), pow().
 Ternary (3-argument) functions: if().
 运算符: +, -, *, /, <, > <=, >=, =, <>.
 一元函数(一个参数):abs(), ceil(), floor(), sin(), cos(), ln(), log2(), log10(), exp(),
sqrt().
 二元函数(两个参数):min(), max(), pow().
 三元函数(三个参数):if().
全部的计算都以单精度32位IEEE754浮点数进行。比较操作符(比如=和<=)在条件为真 时返回1.0,否则返回0.0。例如(a=b)+3在属性“a”与属性“b”相等时返回4,否则返回 3。与MySQL不同,相等性比较符(即=和<>)中引入了一个小的阈值(默认是1e-6)。
如果被比较的两个值的差异在阈值之内,则二者被认为相等。
全部的一元和二元函数的意义都很明确,他们的行为跟在数学中的定义一样。但IF()的行为
需要点详细的解释。它接受3个参数,检查第一个参数是否为0.0,若非零则返回第二个参
数,为零时则返回第三个参数。注意,与比较操作符不同,IF()并不使用阈值!因此在第一
个参数中使用比较结果是安全的,但使用算术运算符则可能产生意料之外的结果。比如,下
面两个调用会产生不同的结果,虽然在逻辑上他们是等价的:
IF ( sqrt(3)*sqrt(3)-3<>0, a, b )
IF ( sqrt(3)*sqrt(3)-3, a, b )
在第一种情况下,由于有阈值,比较操作符<>返回0.0(逻辑假),于是IF()总是返回
‘b’。在第二种情况下,IF()函数亲自在没有阈值的情况下将同样的
sqrt(3)*sqrt(3)-3与零值做比较。但由于浮点数运算的精度问题,该表达式的结果与
0值会有微小的差异,因此该值与零值的相等比较不会通过,上述第二种情况中IF()会返
回‘a’做为结果。

6. 结果分组(聚类)
有时将搜索结果分组(或者说“聚类”)并对每组中的结果计数是很有用的-例如画个漂亮
的图来展示每个月有多少的blog日志,或者把Web搜索结果按站点分组,或者把找到的论
坛帖子按其作者分组。
理论上,这可以分两步实现:首先在Sphinx中做全文检索,再在SQL服务器端对得到的ID
分组。但是现实中在大结果集(10K到10M个匹配)上这样做通常会严重影响性能。
为避免上述问题,Sphinx提供了一种“分组模式”,可以用API调用SetGroupBy()来开启。
在分组时,根据group-by值给匹配项赋以一个分组。这个值用下列内建函数之一根据特定的
属性值计算:
 SPH_GROUPBY_DAY,从时间戳中按YYYYMMDD格式抽取年、月、日
 SPH_GROUPBY_WEEK,从时间戳中按YYYYNNN格式抽取年份和指定周数(自年
初计起)的第一天
 SPH_GROUPBY_MONTH,从时间戳中按YYYYMM格式抽取月份
 SPH_GROUPBY_YEAR,从时间戳中按YYYY格式抽取年份
 SPH_GROUPBY_ATTR,使用属性值自身进行分组
最终的搜索结果中每组包含一个最佳匹配。分组函数值和每组的匹配数目分别以“虚拟”属
性@group和@count的形式返回。
结果集按group-by排序子句排序,语法与SPH_SORT_EXTENDED 排序子句的语法相似。除
了@id和@weight,分组排序子句还包括:
 @group(groupby函数值)
 @count(组中的匹配数目)
默认模式是根据groupby函数值降序排列,即按照“@group desc”
排序完成时,结果参数total_found会包含在整个索引上匹配的组的总数目。
注意:分组操作在固定的内存中执行,因此它给出的是近似结果;所以total_found报告的数
目可能比实际给出的个分组数目的和多。@count也可能被低估。要降低不准确性,应提高
max_matches。如果max_matches允许存储找到的全部分组,那结果就是百分之百准确的。
例如,如果按相关度排序,同时用SPH_GROUPBY_DAY函数按属性“published”分组,那
么:
 结果中包含每天的匹配结果中最相关的那一个,如果那天有记录匹配的话。
 结果中还附加给出天的编号和每天的匹配数目
 结果以天的编号降序排列(即最近的日子在前面)

7. 分布式搜索
为提高可伸缩性,Sphnix提供了分布式检索能力。分布式检索可以改善查询延迟问题(即缩
短查询时间)和提高多服务器、多CPU或多核环境下的吞吐率(即每秒可以完成的查询
数)。这对于大量数据(即十亿级的记录数和TB级的文本量)上的搜索应用来说是很关键
的。
其关键思想是将待搜索数据做水平分区(HP,Horizontally partition),然后并行处理。
分区不能自动完成,您需要:
 在不同服务器上设置Sphinx程序集(indexer和searchd)的多个实例
 让这些实例对数据的不同部分做索引(并检索)
 在searchd的一些实例上配置一个特殊的分布式索引
 然后对这个索引进行查询
这个特殊索引只包括对其他本地或远程索引的引用,因此不能对它执行重新建立索引的操作,
相反,如果要对这个特殊索引进行重建,要重建的是那些被这个索引被引用到的索引。
当searchd收到一个对分布式索引的查询时,它做如下操作:
1. 连接到远程代理
2. 执行查询
3. (在远程代理执行搜索的同时)对本地索引进行查询
4. 接收来自远程代理的搜索结果
5. 将所有结果合并,删除重复项
6. 将合并后的结果返回给客户端
在应用程序看来,普通索引和分布式索引完全没有区别。
任一个searchd实例可以同时做为主控端(master,对搜索结果做聚合)和从属端(只做本地
搜索)。这有如下几点好处:
1. 集群中的每台机器都可以做为主控端来搜索整个集群,搜索请求可以在主控端之间获
得负载平衡,相当于实现了一种HA(high availability,高可用性),可以应对某个
节点失效的情况。
2. 如果在单台多CPU或多核机器上使用,一个做为代理对本机进行搜索的searchd实例
就可以利用到全部的CPU或者核。
更好的HA支持已在计划之中,到时将允许指定哪些代理之间互相备份、有效性检查、跟踪
运行中的代理、对检索请求进行负载均衡,等等。

8. searchd 日志格式
searchd将全部成功执行的搜索查询都记录在查询日志文件中。以下是一个类似记录文件的
例子:
[Fri Jun 29 21:17:58 2007] 0.004 sec [all/0/rel 35254 (0,20)] [lj] test
[Fri Jun 29 21:20:34 2007] 0.024 sec [all/0/rel 19886 (0,20) @channel_id] [lj]
test
日志格式如下
[query-date] query-time [match-mode/filters-count/sort-mode
total-matches (offset,limit) @groupby-attr] [index-name] query
匹配模式(match-mode)可以是如下值之一:
 “all” 代表 SPH_MATCH_ALL 模式;
 “any” 代表 SPH_MATCH_ANY 模式;
 “phr” 代表 SPH_MATCH_PHRASE 模式;
 “bool” 代表 SPH_MATCH_BOOLEAN 模式;
 “ext” 代表 SPH_MATCH_EXTENDED 模式.
排序模式(sort-mode)可以取如下值之一:
 “rel” 代表 SPH_SORT_RELEVANCE 模式;
 “attr-” 代表 SPH_SORT_ATTR_DESC 模式;
 “attr+” 代表 SPH_SORT_ATTR_ASC 模式;
 “tsegs” 代表 SPH_SORT_TIME_SEGMENTS 模式;
 “ext” 代表 SPH_SORT_EXTENDED 模式.

Posted in sphinx, 技术.

Tagged with .


Sphinx增量索引

Sphinx+Mysql+中文分词安装

在实际应用中往往有这么一种情况,数据库数据很大,比如我们的歌曲表,如果我们每次都去更新整个表的索引,对系统得开销将非常大,显然这是不合适,这时我们会发现,每天我们需要更新的数据相比较而言较少,在这种情况下我们就需要使用“主索引+增量索引”的模式来实现实时更新的功能。

这个模式实现的基本原理是设置两个数据源和两个索引,为那些基本不更新的数据建立主索引,而对于那些新增的数据建立增量索引。主索引的更新频率我们可以设置的长一些(可以设置在每天的午夜进行更新),而增量索引的更新频率,我们可以将时间设置的很短(几分钟左右),这样在用户搜索的时候,我们可以同时查询这两个索引的数据。

下面,我们通过一个简单的例子来描述一下怎样实现这种模式

以sphinx.conf中默认的数据为例:

1.先在mysql中插入一个计数表和两个索引表

CREATE TABLE sph_counter(
counter_id INTEGER PRIMARY KEY NOT NULL,
max_doc_id INTEGER NOT NULL
);

//主索引使用(确认之前是否已经建立过该表,如果已经建立,这里就不需要重新建了)

CREATE TABLE `sphinx` (
`id` int(11) NOT NULL,
`weight` int(11) NOT NULL,
`query` varchar(255) NOT NULL,
`CATALOGID` INT NOT NULL,
`EDITUSERID` INT NOT NULL,
`HITS` INT NULL,
`ADDTIME` INT NOT NULL, KEY
`Query` (`Query`)
) ENGINE=SPHINX DEFAULT CHARSET=utf8 CONNECTION=’sphinx://localhost:3312/test1′

//增量索引使用

CREATE TABLE `sphinx1` (
`id` int(11) NOT NULL,
`weight` int(11) NOT NULL,
`query` varchar(255) NOT NULL,
`CATALOGID` INT NOT NULL,
`EDITUSERID` INT NOT NULL,
`HITS` INT NULL,
`ADDTIME` INT NOT NULL, KEY
`Query` (`Query`)
)ENGINE=SPHINX DEFAULT CHARSET=utf8 CONNECTION=’sphinx://localhost:3312/ test1stemmed ‘

2.修改sphinx.conf

source src1
{
sql_query_pre = SET NAMES utf8
sql_query_pre = SET SESSION query_cache_type=OFF
sql_query_pre = REPLACE INTO sph_counter SELECT 1, MAX(id) FROM documents
sql_query = SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content FROM documents \
WHERE id<=( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 ) ... //其他可以默认 } // 注意:sql_query_pre的个数需和src1对应,否则可能搜索不出相应结果 source src1throttled : src1 { sql_ranged_throttle = 100 sql_query_pre = SET NAMES utf8 sql_query_pre = SET SESSION query_cache_type=OFF sql_query_pre = sql_query = SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content FROM documents \ WHERE id>( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 )
}

index test1 //主索引
{
source = src1

}

index test1stemmed : test1 //增量索引
{
source = src1throttled

}

3.重建索引

/usr/local/sphinx/bin/searchd –stop
/usr/local/sphinx/bin/indexer –config /usr/local/sphinx/etc/sphinx.conf –all
/usr/local/sphinx/bin/searchd –config /usr/local/sphinx/etc/sphinx.conf

插入测试数据

INSERT INTO `test`.`documents` (
`id` ,
`group_id` ,
`group_id2` ,
`date_added` ,
`title` ,
`content`
)
VALUES (
NULL , ‘3’, ’11’, NOW( ) , ‘索引合并’, ‘合并两个已有的索引比重新对所有数据做索引更有效率,而且有时候必须这样做(例如在“ 主索引+增量索引”分区模式中应合并主索引和增量索引,而不是简单地重新索引“主索引对应的数据)。因此indexer有这个选项。合并索引一般比重新索引快,但在大型索引上仍然不是一蹴而就。基本上,待合并的两个索引都会被读入内存一次,而合并后的内容需要写入磁盘一次。例如,合并100GB和1GB的两个索引将导致202GB的IO操作(但很可能还是比重新索引少)’
);

执行

SELECT doc . *
FROM documents doc
JOIN sphinx ON ( doc.id = sphinx.id )
WHERE query = ‘索引’

你会发现你刚添加的数据没有被检索出来
然后执行:

SELECT doc.* FROM documents doc join sphinx1 on (doc.id=sphinx1.id) where query=’索引’

你会发现数据是空的,这时我们就需要来更新增量索引了。

通过执行:

/usr/local/sphinx/bin/indexer –rotate –config /usr/local/sphinx/etc/sphinx.conf test1stemmed

命令来更新增量索引(正式使用时,我们可以将该命令配置到系统计划任务中,每隔几分钟执行一次)
–rotate: 该参数可以使我们在不需要停止searchd的情况下,直接加载索引
执行完命令该命令后,我们再来查看一下增量索引的数据


SELECT doc.* FROM documents doc join sphinx1 on (doc.id=sphinx1.id) where query=’索引’

你会发现新添加的数据被检索出来的。

主索引的更新:

/usr/local/sphinx/bin/indexer –rotate –config /usr/local/sphinx/etc/sphinx.conf test1


collected 997 docs, 1.4 MB
sorted 0.3 Mhits, 100.0% done
total 997 docs, 1430054 bytes
total 1.428 sec, 1001459.38 bytes/sec, 698.19 docs/sec

(我们可以设置成每天的午夜执行)

只有在更新了主索引后,结果才会被更新

SELECT doc.* FROM documents doc join sphinx on (doc.id=sphinx.id) where query=’索引’

我们也可以通过合并索引的方式使主索引的数据保持更新

/usr/local/sphinx/bin/indexer –merge test1 test1stemmed –rotate

可以将增量索引test1stemmed合并到主索引test1中去

为创建2个shell脚本,一个用来创建主索引、一个用来创建增量索引(此步可以省略)

1.创建主索引脚本build_main_index.sh

#!/bin/sh
#/usr/local/sphinx/bin/searchd –stop
/usr/local/sphinx/bin/indexer test1 –config /usr/local/sphinx/etc/sphinx.conf >> /var/log/sphinx/mainindexlog
#/usr/local/sphinx/bin/searchd

2.创建增量索引脚本build_delta_index.sh

#!/bin/sh
#/usr/local/sphinx/bin/searchd –stop
/usr/local/sphinx/bin/indexer test1stemmed –config /usr/local/sphinx/etc/sphinx.conf –rotate>> /var/log/sphinx/deltaindexlog
/usr/local/sphinx/bin/indexer –merge test1 test1stemmed –config /usr/local/sphinx/etc/sphinx.conf –rotate >> /var/log/sphinx/deltaindexlog
#/usr/local/sphinx/bin/searchd

每隔5分钟进行索引增量合并,每天2:30重建索引

*/5 * * * * /bin/sh /opt/shell/build_delta_index.sh > /dev/null 2>&1
30 2* * * /bin/sh /opt/shell/build_main_index.sh > /dev/null 2>&1

每周一至周六上早6点增量合并,同日重建索引

1 6 * * 1-6 /bin/sh /opt/shell/build_delta_index.sh > /dev/null 2>&1
1 6 * * 7 /bin/sh /opt/shell/build_main_index.sh > /dev/null 2>&1

参考:
http://www.coreseek.com/uploads/pdf/sphinx_doc_zhcn_0.9.pdf

2009-06-26修订

Posted in sphinx, 技术.

Tagged with , .


Sphinx+Mysql+中文分词安装-实现中文全文搜索

什么是Sphinx
Sphinx 是一个在GPLv2 下发布的一个全文检索引擎,商业授权(例如, 嵌入到其他程序中)
需要联系我们(Sphinxsearch.com)以获得商业授权。
一般而言,Sphinx是一个独立的搜索引擎,意图为其他应用提供高速、低空间占用、高结果
相关度的全文搜索功能。Sphinx可以非常容易的与SQL数据库和脚本语言集成。
当前系统内置MySQL和PostgreSQL 数据库数据源的支持,也支持从标准输入读取特定格式
的XML数据。通过修改源代码,用户可以自行增加新的数据源(例如:其他类型的DBMS
的原生支持)。
搜索API支持PHP、Python、Perl、Rudy和Java,并且也可以用作MySQL存储引擎。搜索
API非常简单,可以在若干个小时之内移植到新的语言上。
Sphinx 是SQL Phrase Index的缩写,但不幸的和CMU的Sphinx项目重名

Sphinx的特性

  • 高速的建立索引(在当代CPU上,峰值性能可达到10 MB/秒);
  • 高性能的搜索(在2 – 4GB 的文本数据上,平均每次检索响应时间小于0.1秒);
  • 可处理海量数据(目前已知可以处理超过100 GB的文本数据, 在单一CPU的系统上可
    处理100 M 文档);
  • 提供了优秀的相关度算法,基于短语相似度和统计(BM25)的复合Ranking方法;
  • 支持分布式搜索;
  • provides document exceprts generation;
  • 可作为MySQL的存储引擎提供搜索服务;
  • 支持布尔、短语、词语相似度等多种检索模式;
  • 文档支持多个全文检索字段(最大不超过32个);
  • 文档支持多个额外的属性信息(例如:分组信息,时间戳等);
  • 停止词查询;
  • 支持单一字节编码和UTF-8编码;
  • 原生的MySQL支持(同时支持MyISAM 和InnoDB );
  • 原生的PostgreSQL 支持.

一、安装所需文件
mmseg-0.7.3.tar.gz 中文分词
http://www.coreseek.com/uploads/sources/mmseg-0.7.3.tar.gz

mysql-5.1.26-rc.tar.gz mysql-5.1.26源代码

sphinx-0.9.8-rc2.tar.gz sphinx-0.9.8-rc2源代码
http://www.sphinxsearch.com/downloads/sphinx-0.9.8-rc2.tar.gz

fix-crash-in-excerpts.patch sphinx支持分词补丁
http://www.coreseek.com/uploads/sources/fix-crash-in-excerpts.patch

sphinx-0.98rc2.zhcn-support.patch sphinx支持分词补丁
http://www.coreseek.com/uploads/sources/sphinx-0.98rc2.zhcn-support.patch

二、开始安装
1.安装libmmseg


tar -zxvf mmseg-0.7.3.tar.gz
cd mmseg-0.7.3
./configure –prefix=/usr/local/mmseg
make
make install
cd ..

安装mmseg完成,测试一下

mmseg
Coreseek COS(tm) MM Segment 1.0
Copyright By Coreseek.com All Right Reserved.
Usage: mmseg

有问题可以尝试执行下面命令

echo ‘/usr/local/mmseg/lib’ >> /etc/ld.so.conf
ldconfig -v
ln -s /usr/local/mmseg/bin/mmseg /bin/mmseg

=================2011-08-26 更新=================

在centos6 g++4.4.4上编辑错误

css/UnigramCorpusReader.cpp: In member function ‘virtual int css::UnigramCorpusReader::open(const char*, const char*)’:
css/UnigramCorpusReader.cpp:89: error: ‘strncmp’ was not declared in this scope
make[2]: *** [UnigramCorpusReader.lo] Error 1
make[2]: Leaving directory `/root/src/sphinx/mmseg-0.7.3/src’
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/root/src/sphinx/mmseg-0.7.3′
make: *** [all] Error 2

解决方法
vi .src/css/UnigramCorpusReader.cpp
第一行加上

#include

然后重新 make
===================================================

2.重新编译mysql
在安装之前先打两个补丁,这个是支持中文必须打的补丁

tar -zxvf sphinx-0.9.8-rc2.tar.gz
cd sphinx-0.9.8
patch -p1 < ../sphinx-0.98rc2.zhcn-support.patch patch -p1 < ../fix-crash-in-excerpts.patch

之前我已安装了mysql5.1.26,这里略过具体安装步骤
mysql编译路径
/root/lemp/mysql-5.1.26-rc/
mysql安装路径
/opt/mysql

安装之前关闭mysql

/opt/mysql/bin/mysql.server stop

接着将sphinx下的mysqlse 文件夹下的数据拷贝到mysql-5.1.26-rc/storage/sphinx 下面
(这样才能在编译mysql的时候把SphinxSE存储引擎编译进去)

cp -rf mysqlse /root/lemp/mysql-5.1.26-rc/storage/sphinx
cd /root/lemp/mysql-5.1.26-rc

make clean
sh BUILD/autorun.sh
#这步是必须的,请勿遗漏

开始重新编译

CFLAGS=”-O3″ CXX=gcc CXXFLAGS=”-O3 -felide-constructors -fno-exceptions -fno-rtti” ./configure –prefix=/opt/mysql –localstatedir=/opt/mysql/var –sysconfdir=/opt/mysql –without-debug –with-unix-socket-path=/opt/mysql/mysql.sock –with-big-tables –with-charset=gbk –with-collation=gbk_chinese_ci –with-client-ldflags=-all-static –with-mysqld-ldflags=-all-static –enable-assembler –with-extra-charsets=gbk,gb2312,utf8 –with-pthread –enable-thread-safe-client –with-innodb –with-plugins=sphinx
make
make install


configure: error: unknown plugin: sphinx

我的解决方法:
重新解压一份mysql source
在执行autorun.sh前修改storage/sphinx的用户和用户组,还有权限
sh BUILD/autorun.sh
./configure -h
查看最低下有否包含了sphinx

=== Sphinx Storage Engine ===
Plugin Name: sphinx
Description: Sphinx Storage Engines
Supports build: static and dynamic
Configurations: max, max-no-ndb

然后再编译

make时错误

../libtool: line 466: CDPATH: command not found
../libtool: line 1144: func_opt_split: command not found
libtool: Version mismatch error. This is libtool 2.2.6, but the
libtool: definition of this LT_INIT comes from an older release.
libtool: You should recreate aclocal.m4 with macros from libtool 2.2.6
libtool: and run autoconf again.
make[1]: *** [conf_to_src] 错误 63
make[1]: Leaving directory `/home/andychu/lemp2/mysql-5.1.26-rc/strings’
make: *** [all-recursive] 错误 1

libtool版本不一至产生错误,可以将已安装的libtool覆盖到编译目录
cp /usr/local/bin/libtool .
再重新编译

编译完成,启动mysql,检查SphinxSE存储引擎是否编译进去

/opt/mysql/bin/mysql.server start
/opt/mysql/bin/mysql -uroot -p

Mysql>
输入
show engines;

+————+———+———————————————————–+————–+—-+————+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+————+———+———————————————————–+————–+—-+————+
| CSV | YES | CSV storage engine | NO | NO | NO |
| SPHINX | YES | Sphinx storage engine 0.9.8 | NO | NO | NO |
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| MyISAM | DEFAULT | Default engine as of MySQL 3.23 with great performance | NO | NO | NO |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
+————+———+———————————————————–+————–+—-+————+
5 rows in set (0.00 sec)

此时我们可以看到已经包含sphinxSE 引擎

3.安装sphinx

cd /root/lemp/sphinx-0.9.8-rc2
./configure –prefix=/usr/local/sphinx –with-mysql=/opt/mysql \
–with-mysql-includes=/opt/mysql/include/mysql –with-mysql-libs=/opt/mysql/lib/mysql \
–with-mmseg-includes=/usr/local/mmseg/include –with-mmseg-libs=/usr/local/mmseg/lib –with-mmseg
make

头文件没找到:

tokenizer_zhcn.cpp:1:30: SegmenterManager.h: 没有那个文件或目录
tokenizer_zhcn.cpp:2:23: Segmenter.h: 没有那个文件或目录


make clean
./configure –prefix=/usr/local/sphinx –with-mysql=/opt/mysql \
–with-mysql-includes=/opt/mysql/include/mysql –with-mysql-libs=/opt/mysql/lib/mysql \
–with-mmseg-includes=/usr/local/mmseg/include/mmseg –with-mmseg-libs=/usr/local/mmseg/lib –with-mmseg


/root/sphinx/sphinx-0.9.8-rc2/src/tokenizer_zhcn.cpp:34: undefined reference to `libiconv_close’
collect2: ld returned 1 exit status

官网解决办法:
In the meantime I’ve change the configuration file and set
#define USE_LIBICONV 0 in line 8179.
修改configure 文件把 #define USE_LIBICONV 0 最后的数值由1改为0
重新编译。


make clean
./configure –prefix=/usr/local/sphinx –with-mysql=/opt/mysql \
–with-mysql-includes=/opt/mysql/include/mysql –with-mysql-libs=/opt/mysql/lib/mysql \
–with-mmseg-includes=/usr/local/mmseg/include/mmseg –with-mmseg-libs=/usr/local/mmseg/lib –with-mmseg

vi configure
输入/define USE_LIBICONV 找到目标行
按i键后将1改成0,按esc,输入:wq保存退出

make
make install

编译时报如下的错误
/usr/local/include/mmseg/freelist.h:22: error: ‘strlen’ was not declared in this scope
vi /usr/local/include/mmseg/freelist.h
或者这个地址
vi /usr/local/mmseg/include/mmseg/freelist.h
加上

#include

再次编译就不会报错了。

复制一份sphinx的配置

cd /usr/local/sphinx/etc
cp sphinx.conf.dist sphinx.conf

4.配置sphinx

修改/usr/local/sphinx/etc/sphinx.conf

type = mysql
# some straightforward parameters for SQL source types
sql_host = localhost
sql_user = root
sql_pass =
sql_db = test
sql_port = 3306 # optional, default is 3306

address = 127.0.0.1 #安全点可以只监听本机

5.索引建立

装好sphinx后在sphinx的目录中有三个目录 分别为bin etc var
bin中 存有sphinx用到的一些执行文件 包括 indexer 索引建立 search 查询工具 searchd 查询服务器 等

为了下面测试方便,我们先将sphinx.conf自带的example.sql脚本倒入的mysql中
//创建了一个test库,并建立了documents测试表和数据

/opt/mysql/bin/mysql -uroot -p < /usr/local/sphinx/etc/example.sql

索引的建立方法为

/usr/local/sphinx/bin/indexer –config /usr/local/sphinx/etc/sphinx.conf test1

test1为资源名称 不写为默认所有都建立索引
附:
建立索引期间可能由于不同版本的数据库导致indexer找不到共享库libmysqlclient.so.16
需要把/opt/mysql/lib/mysql/libmysqlclient.so.16.0.0 这个文件复制到/usr/lib下 或者作软连接即可

6.查询服务器

/usr/local/sphinx/bin/searchd –config /usr/local/sphinx/etc/sphinx.conf 为开启

/usr/local/sphinx/bin/searchd –config /usr/local/sphinx/etc/sphinx.conf –stop 为关闭

sphinx的查询 可以大致分为三种

1 数据库引擎中的查询

2 通过search工具查询
/usr/local/sphinx/bin/search –config /usr/local/sphinx/etc/sphinx.conf test

3 通过php的接口查询 详见sphinxapi.php.

三、在mysql中的使用SphinxSE方式调用Sphinx

1.在mysql中的使用SphinxSE方式调用Sphinx
首先建立一张索引专用表:

CREATE TABLE `sphinx` (
`id` int(11) NOT NULL,
`weight` int(11) NOT NULL,
`query` varchar(255) NOT NULL,
`CATALOGID` INT NOT NULL,
`EDITUSERID` INT NOT NULL,
`HITS` INT NULL,
`ADDTIME` INT NOT NULL, KEY
`Query` (`Query`)
) ENGINE=SPHINX DEFAULT CHARSET=utf8 CONNECTION=’sphinx://localhost:3312/test1′

test1:索引的名称,可以在sphinx.conf中查找到
建立完索引专用表后,我们就可以在mysql中使用它了,例如,在mysql中输入

SELECT doc. * FROM documents doc JOIN sphinx ON ( doc.id = sphinx.id ) WHERE query = ‘doc;mode= any’

运行后,结果记录中将会显示包含doc字符串的所用记录行

关于query的语法,还有sphinx的配置等信息你可以请参考:
http://www.sphinxsearch.com/doc.html

2.中文分词应用
生成词典
进入到mmseg的源代码目录后

cd data
mmseg -u unigram.txt

在data下边会产生一个文件unigram.txt.uni
这个就是生成的字典 然后把字典改名为uni.lib放在可以读取的目录中即可

cp unigram.txt.uni /usr/local/sphinx/uni.lib

修改 sphinx.conf(/usr/local/sphinx/etc/sphinx.conf)配置文件
在索引中加入

charset_type = zh_cn.utf-8
charset_dictpath = /usr/local/sphinx/

数据库中增加一条中文数据

INSERT INTO `test`.`documents` (
`id` ,
`group_id` ,
`group_id2` ,
`date_added` ,
`title` ,
`content`
)
VALUES (
NULL , ‘3’, ‘9’, NOW( ) , ‘sphinx中文搜索’, ‘Sphinx是一个基于SQL的全文检索引擎,可以结合MySQL,PostgreSQL做全文搜索,它可以提供比数据库本身更专业的搜索功能,使得应用程序更容易实现专业化的全文检索。Sphinx特别为一些脚本语言设计搜索API接口,如PHP,Python,Perl,Ruby等,同时为MySQL也设计了一个存储引擎插件。 ‘
);

(如果searchd已经再运行,先kill 它再运行)
注意:在添加完数据后,需要重新加载索引,这样新的数据才能被缓存进去
重建索引,成功后,开启索引监听

/usr/local/sphinx/bin/indexer –config /usr/local/sphinx/etc/sphinx.conf –all
/usr/local/sphinx/bin/searchd –config /usr/local/sphinx/etc/sphinx.conf

在ide硬盘上建索引的速度

indexing index ‘test1’…
collected 423228 docs, 637.2 MB
sorted 125.5 Mhits, 100.0% done
total 423228 docs, 637201412 bytes
total 753.401 sec, 845766.13 bytes/sec, 561.76 docs/sec

这样,就可以在phpmyadmin中进行测试了。

SELECT doc. * FROM documents doc JOIN sphinx ON ( doc.id = sphinx.id )
WHERE query = ‘设计;mode= any ‘

好像没出来。。。。

修改 sphinx.conf
去掉下面的注释

sql_query_pre = SET NAMES utf8

再重启searchd就可以搜出结果了

参考:
http://www.coreseek.com/uploads/pdf/sphinx_doc_zhcn_0.9.pdf
http://www.sphinxsearch.com/wiki/doku.php?id=sphinx_chinese_tutorial
http://www.cnblogs.com/hushixiu/articles/1295605.html
http://blog.xoyo.com/dcyhldcyhl/article/839863.shtml
http://blog.sina.com.cn/s/blog_5aefd9770100axf1.html
http://blog.s135.com/post/360/

2009-06-28更新
编码的解决方法(未经测试)
——————————————————————————-
转换现有表的数据
iconv -f GB18030 -t utf-8 -o dump.sql dump_utf8.sql

也可以不转换,直接使用现有的GBK的数据,但是需要设置连接方式
mysql_query(“SET character_set_client = ‘gbk'”, $conn);
mysql_query(“SET character_set_connection =’gbk'”, $conn); //设置character_set_connection也就同时设置了collation_connection
//mysql_query(“SET collation_connection = ‘gbk'”, $conn);
mysql_query(“SET character_set_results =’utf8′”, $conn);
这三个设置后,查询得到的结果,就是UTF8编码的结果了。合适给SPHINX使用。

mysql_query(“SET SESSION query_cache_type=OFF”, $conn);
//indexer建立索引时的查询,不需要缓存的
——————————————————————————-

2009-06-28更新
coreseek网站好像出问题不能下载咯。
提供安装部分文件下载,共3.6M,包含以下文件
build_delta_index.sh
build_main_index.sh
fix-crash-in-excerpts.patch
mmseg-0.7.3.tar.gz
sphinx-0.9.8-rc2.tar.gz
sphinx-0.98rc2.zhcn-support.patch
sphinx.conf
sphinxapi.php
test.php
test2.php

>>猛击这里下载sphinx安装文件

——————————————————————————-

2009-06-28更新
使用service 控制sphinx
先增加一sphinx用户并属于website组(事先已存在),并修改sphinx目录的属主

useradd -d /usr/local/sphinx -g website -s /sbin/nologin sphinx
chown -R sphinx:website /usr/local/sphinx

创建/etc/init.d/sphinx脚本

#!/bin/sh
# sphinx: Startup script for Sphinx search
#
# chkconfig: 345 86 14
# description: This is a daemon for high performance full text \
# search of MySQL and PostgreSQL databases. \
# See http://www.sphinxsearch.com/ for more info.
#
# processname: searchd
# pidfile: $sphinxlocation/var/log/searchd.pid

# Source function library.
. /etc/rc.d/init.d/functions

processname=searchd
servicename=sphinx
username=sphinx
sphinxlocation=/usr/local/sphinx
pidfile=$sphinxlocation/var/log/searchd.pid
searchd=$sphinxlocation/bin/searchd

RETVAL=0

PATH=$PATH:$sphinxlocation/bin

start() {
echo -n $”Starting Sphinx daemon: ”
daemon –user=$username –check $servicename $processname
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$servicename
}

stop() {
echo -n $”Stopping Sphinx daemon: ”

$searchd –stop
#killproc -p $pidfile $servicename -TERM
RETVAL=$?
echo
if [ $RETVAL -eq 0 ]; then
rm -f /var/lock/subsys/$servicename
rm -f $pidfile
fi
}

# See how we were called.
case “$1″ in
start)
start
;;
stop)
stop
;;
status)
status $processname
RETVAL=$?
;;
restart)
stop
sleep 3
start
;;
condrestart)
if [ -f /var/lock/subsys/$servicename ]; then
stop
sleep 3
start
fi
;;
*)
echo $”Usage: $0 {start|stop|status|restart|condrestart}”
;;
esac
exit $RETVAL

修改权限并加入到service,机器启动时自动启动

chmod 755 /etc/init.d/sphinx
chkconfig –add sphinx
chkconfig –level 345 sphinx on
chkconfig –list|grep sphinx #检查下


service sphinx start #运行
service sphinx stop #停止,官方的脚本在我的as4上有点问题,所以粗鲁的改了下
service sphinx restart #重启
service sphinx status #查看是否运行

检查下已用sphinx用户运行

ps aux |grep searchd
sphinx 24612 0.0 0.3 11376 6256 pts/1 S 14:07 0:00 searchd

>>猛击这里下载sphinx启动脚本

参考:http://www.sphinxsearch.com/wiki/doku.php?id=for_centos_5
http://www.notsofaqs.com/catsdoc/doku.php?id=sphinx:install

Posted in sphinx, 技术.

Tagged with , , .


使用INSERT INTO … ON DUPLICATE KEY… 批量插入或更新

update和replace没有同时操作多条记录的语句,
可以用insert … on durlicate key…代替,可以同时插入或更新多条记录

INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
ON DUPLICATE KEY UPDATE b=value(b),c=value(c);

如果键a有重复则更新b和c字段,没有则插入

Posted in Mysql, 技术.

Tagged with .


分享Excel做的甘特图(Gantt Chart)

什么是甘特图? 释义
甘特图(Gantt Chart)是一种图形化地概述项目活动及其他相关系统进度情况的水平方向的条状图。 甘特图在项目管理的工作分解结构(Work Breakdown Structure)中有广泛应用,它能够直观地反映项目阶段和牵涉活动。

一幅完整的甘特图由横轴和纵轴两部分组成,横轴表示项目的总时间跨度,并以月、周或日为时间单位;纵轴表示各项目涉及的各项活动; 长短不一的条状图则表示在项目周期内单项活动的完成情况及时间跨度。

简单的甘特图可以由手工绘制,复杂的甘特图可以通过专业软件来完成,如微软的MS Project、Excel等。

符我平时用excel做的甘特图

wbs1

点此下载模板:c1g_schedule.rar

还有一个老外做的:projectmanagementgantt.rar

Posted in 其它, 项目管理.

Tagged with , .


正则表达式Web版助手工具

从网上看到的,一个很强大的web版正则工具.对于学习正则有很大的帮助.

工具地址:

https://regexr.com/

https://regex101.com/

Posted in JavaScript/DOM/XML, 技术.

Tagged with .


一个可以在线手写输入的网站

http://www.nciku.cn

 

一些字常常记得怎么写,但是忘记读音了

对于习惯拼音输入的就麻烦了

今天发现这个站不错, 能支持手写识别功能, 当然也支持中文, 还能给出对应字的拼音~

n词酷: http://www.nciku.cn/

Posted in 未分类.

Tagged with .


Farseer – Nginx for Windows 快速配置包

使用 nginx/0.7.59 & PHP/5.292 构建

Nginx 的确是 *ix 系统下非常优秀的 HTTP 服务器,但开发人员而言搭建 Windows 平台的 Nginx + PHP 环境的确非常的繁琐而且容易出错。

如果您有上述的问题,那么这个包能够帮得上您的忙。使用这名为 Farseer 的软件包,能够让您在一分钟内完成 Nginx + PHP for Windows 平台的安装。

一分钟安装

  1. 解压缩安装包,并放在合适的地方,例如本人解压缩到 E:\Farseer\ (后面称这个目录为 $FARSEER)
  2. 配置 Nginx 的 DOCUMENT_ROOT 路径,打开 $FARSEER\conf\nginx.conf 文件。找到相应的配置行,修改您需要的路径,例如 E:\htdocs
    set $htdocs e:/htdocs; # 在这里设定 HTTP 服务器根目录
  3. 好了,这样就可以启动 Nginx 系统了,运行 farseer.exe 即可!

http://code.google.com/p/gracecode/wiki/Farseer

作者Blog: http://www.gracecode.com/

相关错误:

mysql_connect() 找不到
修改php.ini 中exts为ext
extension_dir= .\ext
zend_extension_ts=”./ext/php_xdebug.dll”

404错误
set $htdocs ‘D:\Program Files\wamp\www’; # 目录名中有空格需加上单引号

set $htdocs ‘D:\svn\app\Source\\truck’; # \t 会解析成制表符,所以要再加\

安装uchome时不能得到参数
可以正常安装ucenter,但在uchome安装时不能得到参数

Posted in Nginx, 技术.

Tagged with .


彼得原理

彼得原理(The Peter Principle)

彼得原理的概述 

  管理学家劳伦斯·彼得(Laurence.J.Peter),1917年生于加拿大的范库弗,1957年获美国华盛顿州立大学学士学位,6年后又获得该校教育哲学博士学位,他阅历丰富,博学多才,著述颇丰,他的名字还被收人了《美国名人榜》、《美国科学界名人录》和《国际名人传记辞典》等辞书中。

  彼得原理(The Peter Principle)正是彼得根据千百个有关组织中不能胜任的失败实例的分析而归纳出来的。其具体内容是:“在一个等级制度中,每个职工趋向于上升到他所不能胜任的地位”。彼得指出,每一个职工由于在原有职位上工作成绩表现好(胜任),就将被提升到更高一级职位;其后,如果继续胜任则将进一步被提升,直至到达他所不能胜任的职位。由此导出的彼得推论是,“每一个职位最终都将被一个不能胜任其工作的职工所占据。层级组织的工作任务多半是由尚未达到不胜任阶层的员工完成的。”每一个职工最终都将达到彼得高地,在该处他的提升商数(PQ)为零。至于如何加速提升到这个高地,有两种方法。其一,是上面的“拉动”,即依靠裙带关系和熟人等从上面拉;其二,是自我的“推动”,即自我训练和进步等,而前者是被普遍采用的。

  彼得认为,由于彼得原理的推出,使他“无意间”创设了一门新的科学——层级组织学(Hierarchiolgy)。该科学是解开所有阶层制度之谜的钥匙,因此也是了解整个文明结构的关键所在。凡是置身于商业、工业、政治、行政、军事、宗教、教育各界的每个人都和层级组织息息相关,亦都受彼得原理的控制。当然,原理的假设条件是:时间足够长,五层级组织里有足够的阶层。彼得原理被认为是同帕金森定律有联系的。

彼得反转原理

  在对层级组织的研究中,彼得还分析归纳出彼德反转原理:

  一个员工的胜任与否,是由层级组织中的上司判定,而不是外界人士。如果上司已到达不胜任的阶层,他或许会以制度的价值来评判部属。例如,他会注重员工是否遵守规范、仪式、表格之类的事;他将特别赞赏工作迅速、整洁有礼的员工。总之,类似上司是以输入(input)评断部属。于是对于那些把手段和目的的关系弄反了,方法重于目标、文书作业重于预定的目的、缺乏独立判断的自主权、只是服从而不作决定的职业性机械行为者而言,他们会被组织认为是能胜任的工作者,因此有资格获得晋升,一直升到必须作决策的职务时,组织才会发现他们已到达不胜任的阶层。而以顾客、客户或受害者的观点来看,他们本来就是不胜任的。

爬不完的晋升梯子

  现代的层级组织制度,总是从下面来补充由晋升、辞职、退休、解雇和死亡带来的空缺。人们一直把层级组织中的晋升看作是“攀登成功之梯”或“爬上权力之梯”。

  层级组织通常被比喻为梯子,因为梯子和层级组织确有一些共同的特点。例如,梯子是让人向上爬的,而且年利越高,危险越大。

  • 一个收入固定的人,平时能合理地掌握他的钱财。可一旦当他继承了一笔巨额财产后,他的理财能力就会变得无法胜任。
  • 在军队或政府层级组织中,一个称职的随从晋升为领导时,也会突然不称职。
  • 称职的科学家当被提升为研究院院长时,也可能会变成一个不称职的管理者。

  以上各类晋升,之所骈生不胜任,是因为它需要被提升者具备他以前所在职位所不需要的新能力。

  一个一向负责质量工作的雇员,可能会被提升到一个他比较胜任的督监之职。然后,他或许还能升任管理方面的领导,虽然干起来有点吃力,但是他努力工作,如果层级组织的其它条件有利的话,他还可能达到一种不称职状态──做个部门经理,这可能是他所能爬上的最高一层阶梯了。

  这时,他需要花费大量的时间去做日常工作。如果有一群称职能干的下属的支持和帮助,他还可以勉强完成工作。

  由于他看起来还算称职,加上领导者的威望,他也许会进一步得到晋升,即升任总经理──他现在已经达到了最大不称职状态。

  作为一名总经理,他的主要责任是制定与公司目标和政策紧密相关的决策,从负责质量工作到应付长远的目标和更抽象的观念,他越来越感到力所难及,不仅给公司带来损失,而且给他个人造成很大的伤害。

  某些人很理智地观察到了这种事实,就可能会决定退出这种剧烈竞争,开始一种全新的、更有价值的生活。

  今天,许多人已经开始怀疑这种“爬不完的梯子”的游戏。他们把老一辈人视为彼得原理的受害者,他们不再热衷于建立层级组织,而试着发现自己的生活方式。

  不幸的是,大多数的人并没有付诸行动,而是乐此不疲。

位子越高越好吗

  人们总是以为爬得越高就代表越好,可是环顾四周,我们看到,这种盲目往上爬的牺牲者比比皆是。

  为了便于分析,我们把员工分成三级:胜任、适度胜任以及不胜任。

  奥克曼是莱姆汽修公司的杰出技师,他对目前的职位相当满意,因为不需要做太多方案工作。因此,当公司有意调升他做行政工作时,他很想予以回绝。

  奥克曼的太太艾玛,是当地妇女协进会的活跃会员,她鼓励先生接受升适机会。如果奥克曼升官,全家的社会地位、经济能力也会各晋一级。如此一来她就可以出马竞选妇女协进会的主席,也有能力换部新车、添购新装,还可以为儿子买辆迷你摩托车了。

  奥克曼并不情愿用目前的工作,去换办公室里枯燥乏味的工作。但在艾的劝服与唠叨之下,他终于屈服了。升任六个月之后,奥克曼得了胃溃疡,医生告诫他必须滴酒不沾。艾也开始指责奥克曼和新来的秘书有染,并且把失去主席头衔的责任全部推到他身上。奥克曼的工作时间冗长不堪,但却毫无成就感,因此下班回家后就脾气暴躁。由于彼此不停的指责和争吵,奥克曼夫妇的婚姻彻底失败了。

  另外一个相反的例子是这样的。哈里斯是奥克曼的同事,他也是莱姆公司的优秀技师,而且老板也打算提升他。哈里斯的太太利莎非常了解先生很喜欢目前的工作,他一定不愿意花更多的时间坐办公室,负更多责任。莎没有强迫哈里斯去做一个他不喜欢的工作。因此,哈里斯继续当一名技师,将胃溃疡留给奥克曼独享。哈里斯一直保持开朗的个性,在社区里是个广受欢迎的人物,工作之余,他还担任社区里青年团体的领袖。邻居的车如果需要修理,一定都送到莱姆公司,以回报哈里斯平时对公益事业的热心。哈里斯的老板知道他是公司不可或缺的宝贵资产,所以为他提供了优厚的红利、稳定的工作和一切制度内允许的薪水加级。于是,哈里斯买了一辆新车,为莉莎添购新装,也为儿子买了一辆自行车和棒球手套。哈里斯一家过着舒适美满的家庭生活,他们夫妇幸福的婚姻令亲朋好友非常羡慕。他们在邻里间享有的美誉,正是奥克曼太太梦寐以求的理想。

  每个层级系统都由不同的层级或类别组成,系统中的个体则分别隶属于各个级。如果一个人的能力很强,他就会对人类社会产生下面的贡献,杰出的表现又获得升迁的机会,这样他就会从原来胜任的层级晋升到自己无法胜任的层级。

  世界上每一种工作,都会碰到无法胜任的人。只要给予充分的时间与升迁机会,这个能力不足的人终究会被调到一个不胜任的职务上,他会在这个位子上原地步,把工作搞得一塌糊涂。他的表现不仅会打击同事的士气,而且严重妨害整个组织的效率。

  更为重要的是,这些“南郭先生”们自己也会掉进一个自寻烦恼的陷阱,而且无法自拔,如同上述的奥克曼一样。

彼得原理的影响

  对一个组织而言,一旦组织中的相当部分人员被推到了其不称职的级别,就会造成组织的人浮于事,效率低下,导致平庸者出人头地,发展停滞。因此,这就要求改变单纯的“根据贡献决定晋升”的企业员工晋升机制,不能因某个人在某一个岗位级别上干得很出色,就推断此人一定能够胜任更高一级的职务。要建立科学、合理的人员选聘机制,客观评价每一位职工的能力和水平,将职工安排到其可以胜任的岗位。不要把岗位晋升当成对职工的主要奖励方式,应建立更有效的奖励机制,更多地以加薪、休假等方式作为奖励手段。有时将一名职工晋升到一个其无法很好发挥才能的岗位,不仅不是对职工的奖励,反而使职工无法很好发挥才能,也给企业带来损失。

  对个人而言,虽然我们每个人都期待着不停地升职,但不要将往上爬作为自己的惟一动力。与其在一个无法完全胜任的岗位勉力支撑、无所适从,还不如找一个自己能游刃有余的岗位好好发挥自己的专长。

彼得原理的评价

  彼得原理道破了所有阶层制度之谜。凡一切层级制度组织,如商业、工业、政治、行政、军事、宗教、教育各界,都受彼得原理控制。最明显的莫过于我国政府现行的人事制度。我国有关干部任用和政府现行公务员制度中明确指出,提升到某一级别的职位必须在下一级(或半级)职位中任职达到一定年限,逐层向上提升,并将选拔范围放到最小的圈子,最后的结果正如彼得原理所推导:大部分的领导职位是由不能胜任的人所担任。

  由于企业实行的也是层级制度,也存在同样的隐患。

  由此可以解释:政府为什么效率不高?做领导的不做事,做具体事情的不是领导;国有企业为什么办不好?企业套用政府现在的行政级别制度;为什么官僚在每一个社会中都存在?等等。

  如果简单地将企业的人分成两类,那么将存在两类人。第1类:能胜任现在的工作,但基本已“定型”,不具备自我提升的素质,永远只能做好现职工作,再向上升一级就是错误;第2类:不但能胜任现在的工作,也具备自我学习、自我总结、自我提高的素质和能力,能不断提高自己的能力,从而胜任所有的职位。

  由此可见,企业的用人之道可简单地概括为:发现并培养第2种人。由此推导的结论是:必须充分认识到人力资源管理的重要性,并有效运作,发现(包括招聘和在企业内部发展)并培养企业每一职位的接班人,在人力资源上形成可持续发展的潜力。

  提升是将一名员工从前任职位调到需要负责更多职能、担负更大责任的职位上去。一般,随之而来的是更高的地位和更多的工资。提升的动因可能是对过去工作表现突出的报偿,也可能是企业为了更好地使用个人的才能和能力。

  根据《彼得原理》一书的见解,管理人员有时会被提升到他们所不能胜任的层次。特别是有这样的情况,管理人员在其职位上取得了成就,从而使他提升到较高的职位,但这一职位所需要的才能却常常是他所不具备的。这样的提升会使该管理人员无法胜任工作。这种现象在由销售、财务、生产等部门经理中选拔总经理时表现得最为突出。

  由于表现出色的员工被从原岗位上不断地提升,直到他们不能胜任为止,但这个过程往往是单向的、不可逆的,也就是说,很少被提升者会回到原来他所胜任的岗位上去。因此,这样的“提升”最终的结果是企业中绝大部分职位都由不胜任的人担任。这个推断听来似乎有些可笑,但决非危言耸听,甚至不少企业中的实际情况确实如此。这样的现象还会产生另外一种后遗症,就是不胜任的领导可能反而会阻塞了可能的胜任者提升的途径,其危害之大可见一斑。

  尽管我们必须重视管理人员成长可能性并通过提供更大的发展空间等手段来激发他们的潜能,但彼得原理可以作为一种告诫:不要轻易地进行选拔和提拔。解决这个问题最主要的措施有三个:第一,提升的标准更需要重视潜力而不仅仅是绩效。应当以能否胜任未来的岗位为标准,而非仅仅在现在岗位上是否出色。第二,能上能下决不能只是一句空话,要在企业中真正形成这样的良性机制。一个不胜任经理的人,也许是一个很好的主管,只有通过这种机制找到每个人最胜任的角色,挖掘出每个人的最大潜力,企业才能“人尽其才”。第三,为了慎重地考察一个人能否胜任更高的职位,最好采用临时性和非正式性“提拔”的方法来观察他的能力和表现,以尽量避免降职所带来的负面影响。如设立经理助理的职位,在委员会或项目小组这类组织中赋予更大的职责,特殊情况下先让他担任代理职位等等。

  成功企业的用人之道包括:1、适当引进外来人才,好处就是用现成的人才,避开“彼得原理”所涉及的后果;2、在企业内部逐步提升,重视潜力,重要的职位大多数由所能胜任的人。

 

 

来自”http://wiki.mbalib.com/wiki/%E5%BD%BC%E5%BE%97%E5%8E%9F%E7%90%86

Posted in 经济管理.

Tagged with , .


流行的四种后门技术介绍

曾经饱受木马、后门(以下统称后门)侵害的人们都不会忘记机器被破坏后的惨象,于是人们展开了积极的防御工作,从补丁到防火墙,恨不得连网线都加个验证器,在多种多样的防御手法夹攻下,一大批后门倒下了,菜鸟们也不用提心吊胆上网了…… 可是后门会因此罢休吗?答案当然是否定的。君不见,在风平浪静的陆地下,一批新的后门正在暗渡陈仓……

 

1、反客为主的入侵者

黑客A连接上了网络,却不见他有任何行动,他在干什么呢?我们只能看见他燃起一支烟,似乎在发呆……过了一会儿,他突然把烟头一丢,双手迅速敲击键盘,透过屏幕,我们得知他已经进入了一个企业内部的服务器,一台安装了防火墙、而且深居内部的服务器……他怎么做到的呢?莫非他是神仙?请把镜头回退到刚才那一幕,黑客A在烟雾熏绕中盯着一个程序界面出神,突然,那个界面变动了一下,同时,黑客A也开始敲打键盘,接下来就是熟悉的控制界面。各位也许不相信自己的眼睛了:难道是那台机器自己找上他的?不可能…… 可是这是事实,真的是服务器自己找上来的。黑客A也不是高技术,他只是使用了一种反客为主的后门——反弹木马。

 

众所周知,通常说的入侵都是入侵者主动发起攻击,这是一种类似捕猎的方式,在警惕性高的猎物面前,他们已经力不从心;可是对于使用反弹技术的入侵者来说,他们却轻松许多,反弹木马就如一个狼外婆,等着小红帽亲自送上门去。一般的入侵是入侵者操作控制程序去查找连接受害计算机,而反弹入侵却逆其道而行之,它打开入侵者电脑的一个端口,却让受害者自己与入侵者联系并让入侵者控制,由于大多数防火墙只处理外部数据,对内部数据却闭上眼睛,于是,悲剧发生了。

反弹木马的工作模式如下:受害者(被植入反弹木马服务端的计算机)每间隔一定时间就发出连接控制端的请求,这个请求一直循环到与控制端成功连接;接下来控制端接受服务端的连接请求,两者之间的信任传输通道建立;最后,控制端做的事情就很普通了——取得受害者的控制权。由于是受害者主动发起的连接,因此防火墙在大多数情况下不会报警,而且这种连接模式还能突破内网与外部建立连接,入侵者就轻易的进入了内部的计算机。

虽然反弹木马比起一般木马要可怕,但是它有天生的致命弱点:隐蔽性还不够高,因为它不得不在本地开放一个随机端口,只要受害者有点经验,认出反弹木马不是难事。于是,另一种木马诞生了。

 

2、不安分的正常连接

现在有很多用户都安装了个人HTTP服务器,这就注定了机器会开着80端口,这很正常,但是有谁知这是一个给无数网络管理员带来痛苦的新技术,它让一个正常的服务变成了入侵者的利器。

当一台机器被种植Tunnel后,它的HTTP端口就被Tunnel重新绑定了——传输给WWW服务程序的数据,也在同时传输给背后的Tunnel,入侵者假装浏览网页(机器认为),却发送了一个特殊的请求数据(符合HTTP协议),Tunnel和WWW服务都接收到这个信息,由于请求的页面通常不存在,WWW服务会返回一个HTTP404应答,而Tunnel却忙开了……

 

首先,Tunnel发送给入侵者一个确认数据,报告Tunnel存在;然后Tunnel马上发送一个新的连接去索取入侵者的攻击数据并处理入侵者从HTTP端口发来的数据;最后,Tunnel执行入侵者想要的操作。由于这是“正常”的数据传输,防火墙一样没看见。但是目标没开放80端口怎么办呢?擅自开一个端口等于自杀。但是入侵者不会忘记那个可爱的NetBIOS端口——长年累月开放的139端口,和它分享数据,何乐不为? Tunnel技术使后门的隐蔽性又上了一个级别,可是这并不代表无懈可击了,因为一个有经验的管理员会通过Sniffer看到异常的景象…… Tunnel攻击被管理员击溃了,可是,一种更可怕的入侵正在偷偷进行中……

 

3、无用的数据传输?

眼皮底下的偷窃者——ICMP

ICMP,Internet Control Message Protocol(网际控制信息协议),最常见的网络报文,近年来被大量用于洪水阻塞攻击,但是很少有人注意到,ICMP也偷偷参与了这场木马的战争…… 最常见的ICMP报文被用作探路者——PING,它实际上是一个类型8的ICMP数据,协议规定远程机器收到这个数据后返回一个类型0的应答,报告“我在线”。可是,由于ICMP报文自身可以携带数据,就注定了它可以成为入侵者的得力助手。由于ICMP报文是由系统内核处理的,而且它不占用端口,因此它有很高的优先权。ICMP就像系统内核的亲戚,可以不受任何门卫阻拦,于是,篮子里藏着武器的乡下老人敲响了总统的房门……

使用特殊的ICMP携带数据的后门正在悄然流行,这段看似正常的数据在防火墙的监视下堂而皇之的操纵着受害者,即使管理员是个经验丰富的高手,也不会想到这些“正常”的ICMP报文在吞噬着他的机器。有人也许会说,抓包看看呀。可是,实际应用中,传递数据的ICMP报文大部分肯定是加密过的,你怎么检查?

不过,ICMP也不是无敌的,有更多经验的管理员干脆禁止了全部ICMP报文传输,使得这位亲戚不得再靠近系统,虽然这样做会影响系统的一些正常功能,可是为了避免被亲戚谋杀,也只能忍了。最亲密最不被怀疑的人,却往往是最容易杀害你的人。

 

不正常的邮递员——IP首部的计谋

我们都知道,网络是建立在IP数据报的基础上的,任何东西都要和IP打交道,可是连IP报文这个最基本的邮递员也被入侵者收买了,这场战争永不停歇……为什么呢?我们先略了解一下IP数据报的结构,它分为两个部分,首部和身体,首部装满了地址信息和识别数据,正如一个信封;身体则是我们熟悉的数据,正如信纸。任何报文都是包裹在IP报文里面传输的,通常我们只留意信纸上写了什么,却忽略了信封上是否涂抹了氰酸钾。于是,很多管理员死于检查不出的疑症……

这是协议规范的缺陷导致的,这个错误不是唯一的,正如SYN攻击也是协议规范的错误引起的。相似的是,两者都用了IP首部。SYN是用了假信封,而“套接字”木马则是在信封上多余的空白内容涂抹了毒药——IP协议规范规定,IP首部有一定的长度来放置标志位(快递?平信?)、附加数据(对信的备注),结果导致IP首部有了几个字节的空白,别小看这些空白,它能携带剧毒物质。这些看似无害的信件不会被门卫拦截,可是总统却不明不白的死在了办公室……

入侵者用简短的攻击数据填满了IP首部的空白,如果数据太多,就多发几封信。混入受害者机器的邮递员记录信封的“多余”内容,当这些内容能拼凑成一个攻击指令的时候,进攻开始了……

 

结语

后门技术发展到今天,已经不再是死板的机器对机器的战争,它们已经学会考验人类,现在的防御技术如果依然停留在简单的数据判断处理上,将被无数新型后门击溃。真正的防御必须是以人的管理操作为主体,而不是一味依赖机器代码,否则你的机器将会被腐蚀得面目全非……

来自:http://51ctoeditor.blog.techweb.com.cn/2009/03/18/%e9%bb%91%e5%ae%a2%e9%ab%98%e6%89%8b%e4%b8%ba%e6%82%a8%e8%ae%b2%e8%a7%a3%e7%9b%ae%e5%89%8d%e6%b5%81%e8%a1%8c%e7%9a%84%e5%9b%9b%e7%a7%8d%e5%90%8e%e9%97%a8%e6%8a%80%e6%9c%af/

Posted in 安全, 技术.

Tagged with , .