广州服装玩具饰品图书等批发市场
众所皆知,广州市全球闻名的服装和商品批发地之一。但是在这块寸土寸金的地方,同样有着不同的价格,作为一个生意人,一个长期、稳定的优质货源,有多么重要不言而喻。接触过许多外地来的朋友都抱怨:广州这么大,好货源哪里找呢?确实,即使是在广州市内,也有很多挂羊头卖狗肉的地方,举例来説,就曾经在广园新村看见一个箱子 40 元,在一德路就卖 180 (rmb),还声称广州最低!同时,每天都要的经济支出也是来自广州批货的朋友头大的问题-动輒两三百元的住宿费,加上其他费用,一天基本消费最少就三百元起了。就算如此,也很难清楚火车站商圈的货源,更別説更多有优质货源的地方了,很多好朋友来了两天就草草的结束广州的『找货』之行,不但没有找到优质的货源,反而要因此经常往返广州真是得不偿失。根据我们驻点广州和同事朋友的帮助,对于广州各大批发市场有些心得,就整理下手边广州服饰批发採购货源资料,希望对寻找货源的新手朋友们有所帮助。
----------
A. 广州火车站商圈、白马商圈:
火车站为依託、以外贸品为主(确实这里有不少外贸精品,出入的老外非常多,这里可爆个内幕,有朋友家里是做服装的,白马附近很多服装是沙河或者十三行的低档货,常常拿 10 元的货来这里卖 50、80 元甚至更多的也有),包括往站西走那边走的路上几个纯外贸服装的商城和火车站的地五大道,地下错综复杂的服装档口网络延绵数站路,出口有数十个之多,新手真的会在里面迷路,这里面多是做老外生意的,中国人去了常常会被冷眼相待。这边老闆不愁生意,统一的特点就是有现货,他们囤积了大量的货,你在这边很难杀价的原因就是附近很多家店面都是同个老闆的产业,他们将价格定死了。这里的商圈是许多学生卖家和年轻人喜欢批发採购的地点,因为离火车站近,没理由捨近求远,还有就是这里的服装真的很吸引人,在加上穿着火辣、態度热情的辣妹,很容易就敞开腰包让她们宰你温柔一刀!很多人也许来过广州很多次候才能发现,这边的货回去跟当地的服装在价格上並没有很明显的优势,甚至价格上有过之而无不及,因为这里的货否遍特点就是:「漂亮而贵」而且基本上都是採取一个大店面请许多「靚女」的形式,所以很难讲价。适合高档地段,目标人群起码是公司白领,对生活质量有一定追求的客群。如果是一些普通的地段,中低或是大众客群消费的服装,真的不推荐这里拿货。其实做生意的老手想想就知道了,火车站这种黄金地段,那种商业氛围下租金多少不言而喻,每年租金十几外甚至几十万的『小』店並不在少数。
评级:★★★
理由:价格偏高,並有少量以次等货充当高等货。
适合客群:以外贸品为主,针对中高阶层客群,注重商品质量,销路十分畅通的卖家。
普遍价格:100 (rmb) 元左右或以上每件。
----------
B. 站西商圈:
这里是很多年轻人、潮人的必到之地,位於广州火车站西,许多潮人潮衫都出自这里,同样,真正有工厂、工作室的店家比较少在这里进驻,通常是老闆与工厂的合作模式。这里能掏到一些物美价廉的好东西,价位比白马商圈要便宜一些,质量方面属于中档,款式一般跟着「瑞丽」等时尚杂志走,很多年轻的潮人和靚女都在这边进货,大陆掏宝网上很多的服装这边也都有的卖,卖服装的有一半左右甚至更多都是来自广州的货源(当然包括台北的五分埔),这里当然是重镇之一。总之这里非常适合定位中等的潮人辣妹帅哥来此找货,作为货源的话还需要反复的筛选,千万不要看到了喜欢的就头脑发热,买下去~还是要精挑细选般。补充:这里比白马商圈容易杀价些,因为毕竟这边都是中小卖家,还是得看个人功力了。
评级:★★★★
理由:价格和质量中等,款式齐全,符合当下年轻人的口味。
适合客群:年轻人、潮人、靚女。
普遍价格:30 ~ 100 (rmb) 元每件,有高有低。
----------
C. 沙河商圈,十三行(重点介绍)
很多新手受老手卖家灌输的观念:「那边都是些低档货!」确实,这里都是些低档货,但绝对是 80% 的卖家首选,因为这里有各位来广州的梦想-便宜!在这里我只能説:没有最低,只有更低!其实很多朋友买的衣服都是出自这里的,不要看他一百十几块多的甚至更贵,经过一层层的转手确实价格高到有点离谱也试算正常的了。毕竟服装业目前来説还是个热门的暴利行业。广州沙河无疑是广州服装最大的集散地,像广州的十三行、站西路、白马都有很多老闆会去沙河掏货。这里就像一个大染缸,有好有次、有优有良,当然如果你想在这里买到所谓的外贸货可能没有,但是绝对有你需要的东西!沙河服装批发早上开门的时间可能是广州所有的服饰批发市场最早的,大概 3、4 点就开始了,一般来説 3、4 点去拿货的人都是广州別的服装批发市场的老闆去哪里掏货。他们拿完获救回去要自己开门做生意。还有在少数时候,要是运气好的话还可以碰到商家的尾货在甩卖,价格非常的便宜,一般都是按斤算的,广州人称之为「发霉货」,听这词就知道它有多便宜了,简直到了「吐血」的地步,曾经看过商家甩卖女士短T恤,1元1件,不挑款,这些都是外面市场至少卖 20 元的款式,甚至在其他卖场看到同款卖 30 元,这就是批发价阿!即使是平常,这种许多女大学生、少女喜欢穿的 T 恤,在上下九也能以 8 元到 10 元的价格搞定。拿到其他市场上真的想不赚钱都不行阿!沙河大的服装批发诚有万佳批发市场、沙河第一、第二成衣批发市场、沙东有利批发市场南城、沙东有利国际服装批发市场等,要耐心、要有脚力,如果你是娇滴滴的女子,请穿球鞋,因为穿的得体大方在这里很难得到满意报价的,因为一看就像是逛街的,不像是来批货的阿。因为市场普遍开始做生意的时间早,所以关门时间也早。一般在旺季的时候做到下午五点左右,但是有一些一两点就开始关门休息去了,要是淡季的话一般在 11 点左右就有商家开始关门。所以要是打算去沙河拿货那就要去的比较早。沙河做服装的商家一般都是自产自销,所以他们都是按照一天大概卖了多少件就做多少件,看见自己满意的货要是有现货的话就马上拿了,这一点就要靠你的眼力了,不然一些比较热销的款你去拿货时候都只能等第二天或是下订单第二天来取,怎么和老闆谈就看个人功力了。不过这里的老闆很樸实,没有白马那边的架子,一边是靠薄利多销,一边是靠暴利致富 … (透过和这里老闆的交情得知,基本上他们都有自己的档口,早上卖衣服之餘翻翻国外杂志,觉得好的就马上要店里的人去打版,下午或者晚上就能出货 … @@)
评级:★★★★★★★
理由:全中国最好的中低档服装货源之一,只有想不到的价格,没有买不到的价格。
适合客群:中低端、平民化路线的大中小老闆。
普遍价格:10 ~ 30 (rmb) 元每件,甚至更低。
----------
补充:
广州批发採购的行规,就是『拿货』和『打包』两个概念,一件 10 元的女装可能波动 2 元左右,拿货就是混拿,每件拿个两三件的,但是如果你每款 10 件甚至更多打包,要的量大,就会给你『打包价』。下面谈谈拿了那么多货怎么办的事,沙河拿货发物流的话非常方便,每一嶒都会有物流公司搬运工在揽活,一般帮你般货去物流公司是 10 块钱而且他们会帮你把货物用编织袋打好包裹,如果你要是拿的货比较多不想带着货物逛街的话,你可以把货存在批发商的档口那裏,不过一定要记得千万別把小票弄丟,等你全部拿完了要走的时候,你可以把小票给搬运工,让他们帮你去取货在一起般下去(你可以多问批发商要一张小票)。物流一般是七天左右(海运)到臺湾,费用部分一般都是开价 300 ~ 350 元/材(正常都要已含海运费、臺湾海关报关费、拆柜费、提单费、关税等、臺湾内陆宅配)
广州市批发城全集
▉ 广州礼品饰品玩具文具市场名录
国际玩具文具精品广场
主要产品:玩具文具礼品精品喜庆用品
地 址:一德西路390號
公车路线:公车站名:一德西站公交线路车:4 8 61 82 86 243 134
艺景园精品广场
主要产品:玩具文具礼品精品
地 址:一德东路85號
公车路线:公车站名:一德东站公交线路车:4 8 61 82 86 243 134
德宝交易市场
主要产品:玩具文具礼品精品喜庆用品
地 址:一德路190號
公车路线:公车站名:一德西 解放南公交线路车:4 8 61 82 273 243 134 86 244 552
一德谊园精品文具批发市场
主要产品:玩具精品饰品
地 址:一德西路423號
公车路线:公车站名:一德西站公交线路车:4 8 61 82 86 243 134
谊园文具玩具精品市场
主要产品:玩具文具礼品精品
地 址:黄沙大道30號
公车路线:公车站名:黄沙码头站公交线路车:1 6 9 15 38 57 64 75 70 81 123 181 217 236 270
高雅月曆礼品文化精品城
主要产品:月曆礼品文化精品
地 址:广州市机场路63號
泰康城广场
主要产品:精品、饰品、珠宝首饰、帽子等产品
地 址:广州市越秀区泰康路111號
德进批发市场
主要产品:工艺品,精品
地 址:一德路235-243號
荔湾广场
主要产品:精品、礼品、珠宝首饰
地 址:广州市长寿西路
万菱广场
主要产品:玩具、文具、精品
地 址:广州市解放南路39號(一德路及解放南路交界)
朗能文具精品批发市场
主要产品:文具、精品、饰品等
地 址:一德西路435號
中港玩具精品批发城
主要产品:玩具文具精品业
地 址:一德西路399號
嘉乐斯精品玩具城
主要产品:玩具文具礼品精品
地 址:一德西路423號
精锐玩具精品批发中心
主要产品:玩具文具礼品精品
地 址:中山八路20號
金晋精品广场
主要产品:玩具文具礼品精品
地 址:海珠广场 乔光西路
朝阳文化用品批发市场
主要产品:文化用品
地 址:芳村花地大道中238號
华南文化用品批发市场
主要产品:文化用品、纸品业
地 址:南岸路44號
海印二沙体育精品廊
主要产品:体育用品、服装
地 址:东山区二沙岛体育训练基地旁
南澳批发市场
主要产品:文具文体用品
地 址:南岸路河柳街1號
新节拍琴行乐器总汇
主要产品:中西乐器、配件、音乐书谱
地 址:先烈东路4-29號楼
体院体育用品街市
主要产品:体育用品、服装
地 址:广州大道北体育学院外
▉ 广州通讯产品、摄影器材批发市场
批发市场名录:广州通讯产品、摄影器材批发市场一説到通讯产品,人们便会想到了手机。在广州,销售手机的商铺令人眼花繚乱,到底有哪几个通讯产品的专业市场呢?还有在摄影器材批发市场迅速发展的今天,又有哪几家摄影器材批发市场呢?下面让我们一起去看看广州到底有哪些通讯产品、摄影器材批发市场:陵园西通讯产品专业街位於东山区陵园西路,中华广场的对面,烈士陵园的旁边。主要经营通讯机具及其配件的批发零售。
陵园西通讯城 位於东山区陵园西路。主要经营通讯机具及配件,其二楼还经营二手通讯器材的交易。
新蒂电子通讯城 位於东山区中山三路53號,中华广场旁边。主要经营通讯机具及配件。
广州电子城 位於荔湾区西堤二马路16號,文化公园旁。主要经营通讯机具及配件。
中百电子城 位於荔湾区西堤二马路。主要经营通讯机具及配件。
德兴西堤电子城 位於西堤德兴路,文化公园旁。主要经营通讯机具及配件。
广州市日用工业品交易市场 位於荔湾区西堤二马路。主要经营通讯器材、日用电器、摄影器材。
南太日用工业品批发市场 位於荔湾区西堤二马路。主要经营通讯机具及配件、日用电器。
文园电器通讯器材交易市场 位於荔湾区人民南路45號、文化公园右侧。主要经营通讯机具及配件、日用电器等。
广东省通讯产品交易中心 位於越秀区东风中路,市总工会附近。主要经营通讯机具及配件。
广州鸿运摄影器材城 位於东山区大沙头二马路东船上街。主要经营摄影器材及其配套产品。
盛贤鸿运摄影器材城 位於东山区大沙头二马路东船上街。主要经营摄影器及二手摄影器材。
▉ 广州图书、音像製品批发市场
批发市场名录:广州图书、音像製品批发市场隨着中国图书业,音像业规模的迅速成长,各类图书、音像的市场总流量也得到稳步的增长。专业书店、音像店,通过专业的流通管道应运而生。在广州的图书音像市场上,有以下多个批发市场:广州市新华书店位於越秀区北京路276號。主要经营综合性的书籍的批发零售。
广州市科技书店 位於越秀区北京路336號。主要经营科技类的综合书籍。
广州市古籍书店 位於越秀区北京路338號。主要经营各类书法读物以及其他书籍。
广东省外文书店 位於越秀区北京路326號。主要经营各类书籍、外语教材。
广州市儿童书店 位於越秀区北京路314號。主要经营儿童类书籍、读物。
广州购书中心位 於天河区天河路123號。体育中心的右侧。主要经营各类图书、教材及各类音像製品。
广州市考试书店 位於东山区环市东路465號,广工北门对面。主营自学教材,考试教材类书籍。
金羊书店 位於东山区东风东路,羊城晚报社前。主要经营各类图书、书刊、读物。
广东音像城 位於白云区机场路118~122號,北临广州白云机常主要经营音像製品批发零售。
广东省图书批发中心 位於东山区大沙头东湖路。主要经营各类图书、音像製品的批发零售。
新东园图书批发市场 位於东山区沿江东路414,在大沙头附近。主要经营各类图书、报纸杂誌的批发。
广州市图书批发市场 位於海珠区海印桥南建基路。主要经营各类图书批发
▉ 广州主要眼镜钟錶批发市场
广州主要眼镜钟錶批发市场九龙钟錶行
主要产品:各种钟錶及配件
地址:站西群英路3號
广州信江眼镜贸易中心
主要产品:现代化的眼镜
批发地址:广州市人民中路250號
广州信江眼镜贸易中心是广州信江贸易有限公司投资开发的大型眼镜批发市场,在2003年5月9日正式开张营业,她的开张营业使广州眼镜批发市场面积遽增1倍,真正形成了全国三大眼镜批发市场北京、丹阳、广州三足鼎立的形势。该中心位於广州繁华的人民中路,是属於传统眼镜贸易的黄金地带,同广州眼镜城抵足而立,共同形成了一条代表广州眼镜批发行业形象的靚丽的风景线。
广东(国际)眼镜贸易中心
主要产品:国内外品牌眼镜
地址:广州市光复中路313號
南方钟錶交易中心
主要产品:各种钟錶及配件
地址:环市西路145號后座
站西钟錶城
主要产品:各种钟錶及配件
地址:站西群英路5號
华南钟錶批发市场
主要产品:各种钟錶及配件
地址:站西路57號
东方表城
主要产品:各种钟錶及配件
地址:站西群英路5號
南方眼镜专业市场
主要产品:眼镜类及配件光学仪
位址:人民中路317號
广州眼镜城
主要产品:眼镜类及配件光学仪
位址:人民中路260號
▉ 广州文物、古玩、玉器批发市场
批发市场名录:广州文物、古玩、玉器市场在人们生活富餘的同时,越来越多的人喜好收藏文物、古玩、以及玉器。广州素为岭南文化之渊藪,历史源远流长、城市文化气息极为浓厚。荔湾区西关一带做为广州传统商业文化的渊源之地,自是文物、古玩、玉器市场的驻地。
西关古玩市场长久以来已形成了一定的规模,自是品种繁多、琳瑯满目。其中座落于龙津西路泮溪酒家旁的广州西关古玩城,由於文化渊源和常驻有一些颇有实力的、活跃於国内及港澳古玩界、拍卖界的古玩商,因而兴旺不已。在这裏也常能看到一些珍品级的好东西出现。
此外,还有其他几个较为出名的古玩市场:
源胜陶瓷玉器工艺街 位於荔湾区带河路源胜街。
主要经营陶瓷玉器、古玩钱币,古旧家俬、奇珍异石等。
新源胜玉器街 位於荔湾区长寿西新源胜街。
主要经营玉器、工艺品、水晶、首饰包装工具等。
华林玉器专业街、华林玉器大楼、华玉玉器商场 位於华林新街,华林寺附近。
主要经营玉器、工艺品、首饰、水晶等。
华瀚古玩玉器商场 位於荔湾区带河路185號。
主要经营古旧陶瓷、文房四宝、字画杂项等。
广州文物总店 位於东山区文德北路172號。
主要经营古旧陶瓷、文房四宝、古旧家俬、奇珍异石等。
清平古玩钱币市场 位於荔湾区清平路。
主要经营古玩杂项、古旧钱币、奇珍异石等。
▉ 广州化妆品批发市场
广州市目前是全国美容美髮化妆品交易的重要基地,每年的美容美髮、化妆品交易额佔到全国的四成以上,广州已成为中国的美丽中枢。而目前整体规模高居亚太地区榜首的广州美博城可以説是中国美丽领地最重要的亮点了,在广州美博城的带领下,广州美容美髮、化妆用品批发市场也空前地兴旺起来。广州到底还有哪些化妆品、美容美髮、洗涤用品批发市场呢?
广州美博城 位於白云区广园西路121號,火车站与白云机场的衔接处,交通畅顺,辐射力强。是一家规模宏大、造型优美、软硬设施一流的化妆品、美容美髮、洗涤用品市常目前已有国内外400多家知名化妆品品牌厂进驻,各类产品琳瑯满目,魅力四射。
兴发广场 位於白云区机场路138號,广州中医药大学附近。
主要经营化妆品、洗涤用品、美容美髮用品的批发零售。
怡发广场 位於白云区机场路96~98號,在广州中医药大学附近。
主要经营化妆品、洗涤用品、美容美髮器材的批发零售。
中人化妆品城 位於机场南路兴发广场二期二楼。
主要经营化妆品、洗涤用品、美容美髮器材的零售与批发。
洗涤、化妆品、美容美髮用品专业街 位於荔湾区长寿东路、上下九步行街的附近。
主要经营洗涤用品、化妆品、美容美髮用品器材的批发与零售。
服装批发市场进货技巧(一)
1. 服装买家应该先流览一下批发市场,看看自己想购买的服装有几个档口卖。
2. 选定一个档口位置好的开始问价,因为档口位置好一般价格也要高一些。先问要价,然后问最低价,同时很客气地説:『我也刚来看,不太清楚价格,到別处问问您不介意吧?要是您这裏要最便宜我再回来。』有道理也有礼貌,批发商也不好为难你。
3. 到下一个摊位按上一个程式走,比如当对方提出最低价为150元的时候,就説:『刚才那边还只要120元,你这裏要150元,我再看看吧。』对方一定会説:『那你説多少吧。』这时候你可千万不要报价,仍然和和气气地让批发商报最低价,然后再比较。在批发商用降价劝説你拿货的时候也要“义无反顾”地离开,因为这个价钱的水分一定仍然不小。假如对方不再挽留你,説明这个价钱应该接近底价了。
当档口走得差不多的时候,服装买家可以知道大概批发商能接受的底价大概是多少了,然后“狠砍”一个服装不能接受的价钱,然后再往上抬一些,最终能在比较合理的价格成交。
服装买家大可不必担心批发商的利润,因为他们主要靠批发服装赚钱,靠的是走量赚钱。另外,很多服装的成本价低得让人难以置信。
服装买家进货与其和批发商“砍价”,不如让批发商之间互相“砍价”。据説,这种方法多少还借鉴了博弈论的思想。当然,上面的方法是真对服装买家进入新的批发市场而言的,如果与服装批发商建立起了稳定的供货关係,大可以省去这些砍价的麻烦。
服装批发市场进货技巧(二)
我们进货时看中一款产品,是你认为一定好卖的,一定会火的产品,我想这个时候一般会有三个选择,而这三个选择也分別説明你的经验到底有多少~是菜鸟还是老鸟一眼便看出来!
(1) 马上把进货
这説明你是个初级菜鸟,在中国这个市场,倣冒是最具中国特色的,不管哪个品牌的东西,只要款式好、销量好,那就一定能找到倣冒的,所以説是菜鸟,因为你没有货比三家!
(2) 货比三家,然后找到价格最低的进货
你能找到价格最低的説明你有一定的经验了,你可以脱离菜鸟的级別了,但是你还是个雏儿,许多东西虽然款式一样,但是品质一定会有区別的,你忘了还有一句俗语:”一分钱,一分货”
(3) 不进最贵的,也不进最便宜的,而是进性价比最高的!
这是老鸟级別的了,当你达到这个水准的时候,我相信你的生意一定不错,同时我相信你已经非常热爱这个行业了,只有真正用心的人才会达到这个水准,这个水准要求你要有一双慧眼,能看出产品的品质,一上手能知道是什么布料,能做到这一点的太少了。
HBase性能调优 | Ken Wu's Blog
因官方Book Performance Tuning部分章节没有按配置项进行索引,不能达到快速查阅的效果。所以我以配置项驱动,重新整理了原文,并补充一些自己的理解,如有错误,欢迎指正。
配置优化
zookeeper.session.timeout
默认值:3分钟(180000ms)
说明:RegionServer与Zookeeper间的连接超时时间。当超时时间到后,ReigonServer会被Zookeeper从RS集群清单中移除,HMaster收到移除通知后,会对这台server负责的regions重新balance,让其他存活的RegionServer接管.
调优:
这个timeout决定了RegionServer是否能够及时的failover。设置成1分钟或更低,可以减少因等待超时而被延长的failover时间。
不过需要注意的是,对于一些Online应用,RegionServer从宕机到恢复时间本身就很短的(网络闪断,crash等故障,运维可快速介入),如果调低timeout时间,反而会得不偿失。因为当ReigonServer被正式从RS集群中移除时,HMaster就开始做balance了(让其他RS根据故障机器记录的WAL日志进行恢复)。当故障的RS在人工介入恢复后,这个balance动作是毫无意义的,反而会使负载不均匀,给RS带来更多负担。特别是那些固定分配regions的场景。
hbase.regionserver.handler.count
默认值:10
说明:RegionServer的请求处理IO线程数。
调优:
这个参数的调优与内存息息相关。
较少的IO线程,适用于处理单次请求内存消耗较高的Big PUT场景(大容量单次PUT或设置了较大cache的scan,均属于Big PUT)或ReigonServer的内存比较紧张的场景。
较多的IO线程,适用于单次请求内存消耗低,TPS要求非常高的场景。设置该值的时候,以监控内存为主要参考。
这里需要注意的是如果server的region数量很少,大量的请求都落在一个region上,因快速充满memstore触发flush导致的读写锁会影响全局TPS,不是IO线程数越高越好。
压测时,开启Enabling RPC-level logging,可以同时监控每次请求的内存消耗和GC的状况,最后通过多次压测结果来合理调节IO线程数。
这里是一个案例?Hadoop and HBase Optimization for Read Intensive Search Applications,作者在SSD的机器上设置IO线程数为100,仅供参考。
hbase.hregion.max.filesize
默认值:256M
说明:在当前ReigonServer上单个Reigon的最大存储空间,单个Region超过该值时,这个Region会被自动split成更小的region。
调优:
小region对split和compaction友好,因为拆分region或compact小region里的storefile速度很快,内存占用低。缺点是split和compaction会很频繁。
特别是数量较多的小region不停地split, compaction,会导致集群响应时间波动很大,region数量太多不仅给管理上带来麻烦,甚至会引发一些Hbase的bug。
一般512以下的都算小region。
大region,则不太适合经常split和compaction,因为做一次compact和split会产生较长时间的停顿,对应用的读写性能冲击非常大。此外,大region意味着较大的storefile,compaction时对内存也是一个挑战。
当然,大region也有其用武之地。如果你的应用场景中,某个时间点的访问量较低,那么在此时做compact和split,既能顺利完成split和compaction,又能保证绝大多数时间平稳的读写性能。
既然split和compaction如此影响性能,有没有办法去掉?
compaction是无法避免的,split倒是可以从自动调整为手动。
只要通过将这个参数值调大到某个很难达到的值,比如100G,就可以间接禁用自动split(RegionServer不会对未到达100G的region做split)。
再配合RegionSplitter这个工具,在需要split时,手动split。
手动split在灵活性和稳定性上比起自动split要高很多,相反,管理成本增加不多,比较推荐online实时系统使用。
内存方面,小region在设置memstore的大小值上比较灵活,大region则过大过小都不行,过大会导致flush时app的IO wait增高,过小则因store file过多影响读性能。
hbase.regionserver.global.memstore.upperLimit/lowerLimit
默认值:0.4/0.35
upperlimit说明:hbase.hregion.memstore.flush.size 这个参数的作用是当单个Region内所有的memstore大小总和超过指定值时,flush该region的所有memstore。RegionServer的flush是通过将请求添加一个队列,模拟生产消费模式来异步处理的。那这里就有一个问题,当队列来不及消费,产生大量积压请求时,可能会导致内存陡增,最坏的情况是触发OOM。
这个参数的作用是防止内存占用过大,当ReigonServer内所有region的memstores所占用内存总和达到heap的40%时,HBase会强制block所有的更新并flush这些region以释放所有memstore占用的内存。
lowerLimit说明: 同upperLimit,只不过lowerLimit在所有region的memstores所占用内存达到Heap的35%时,不flush所有的memstore。它会找一个memstore内存占用最大的region,做个别flush,此时写更新还是会被block。lowerLimit算是一个在所有region强制flush导致性能降低前的补救措施。在日志中,表现为 “** Flush thread woke up with memory above low water.”
调优:这是一个Heap内存保护参数,默认值已经能适用大多数场景。
参数调整会影响读写,如果写的压力大导致经常超过这个阀值,则调小读缓存hfile.block.cache.size增大该阀值,或者Heap余量较多时,不修改读缓存大小。
如果在高压情况下,也没超过这个阀值,那么建议你适当调小这个阀值再做压测,确保触发次数不要太多,然后还有较多Heap余量的时候,调大hfile.block.cache.size提高读性能。
还有一种可能性是?hbase.hregion.memstore.flush.size保持不变,但RS维护了过多的region,要知道 region数量直接影响占用内存的大小。
hfile.block.cache.size
默认值:0.2
说明:storefile的读缓存占用Heap的大小百分比,0.2表示20%。该值直接影响数据读的性能。
调优:当然是越大越好,如果写比读少很多,开到0.4-0.5也没问题。如果读写较均衡,0.3左右。如果写比读多,果断默认吧。设置这个值的时候,你同时要参考?hbase.regionserver.global.memstore.upperLimit?,该值是memstore占heap的最大百分比,两个参数一个影响读,一个影响写。如果两值加起来超过80-90%,会有OOM的风险,谨慎设置。
hbase.hstore.blockingStoreFiles
默认值:7
说明:在flush时,当一个region中的Store(Coulmn Family)内有超过7个storefile时,则block所有的写请求进行compaction,以减少storefile数量。
调优:block写请求会严重影响当前regionServer的响应时间,但过多的storefile也会影响读性能。从实际应用来看,为了获取较平滑的响应时间,可将值设为无限大。如果能容忍响应时间出现较大的波峰波谷,那么默认或根据自身场景调整即可。
hbase.hregion.memstore.block.multiplier
默认值:2
说明:当一个region里的memstore占用内存大小超过hbase.hregion.memstore.flush.size两倍的大小时,block该region的所有请求,进行flush,释放内存。
虽然我们设置了region所占用的memstores总内存大小,比如64M,但想象一下,在最后63.9M的时候,我Put了一个200M的数据,此时memstore的大小会瞬间暴涨到超过预期的hbase.hregion.memstore.flush.size的几倍。这个参数的作用是当memstore的大小增至超过hbase.hregion.memstore.flush.size 2倍时,block所有请求,遏制风险进一步扩大。
调优: 这个参数的默认值还是比较靠谱的。如果你预估你的正常应用场景(不包括异常)不会出现突发写或写的量可控,那么保持默认值即可。如果正常情况下,你的写请求量就会经常暴长到正常的几倍,那么你应该调大这个倍数并调整其他参数值,比如hfile.block.cache.size和hbase.regionserver.global.memstore.upperLimit/lowerLimit,以预留更多内存,防止HBase server OOM。
hbase.hregion.memstore.mslab.enabled
默认值:true
说明:减少因内存碎片导致的Full GC,提高整体性能。
调优:详见 http://kenwublog.com/avoid-full-gc-in-hbase-using-arena-allocation
其他
启用LZO压缩
LZO对比Hbase默认的GZip,前者性能较高,后者压缩比较高,具体参见?Using LZO Compression 。对于想提高HBase读写性能的开发者,采用LZO是比较好的选择。对于非常在乎存储空间的开发者,则建议保持默认。
不要在一张表里定义太多的Column Family
Hbase目前不能良好的处理超过包含2-3个CF的表。因为某个CF在flush发生时,它邻近的CF也会因关联效应被触发flush,最终导致系统产生更多IO。
批量导入
在批量导入数据到Hbase前,你可以通过预先创建regions,来平衡数据的负载。详见?Table Creation: Pre-Creating Regions
避免CMS concurrent mode failure
HBase使用CMS GC。默认触发GC的时机是当年老代内存达到90%的时候,这个百分比由 -XX:CMSInitiatingOccupancyFraction=N 这个参数来设置。concurrent mode failed发生在这样一个场景:
当年老代内存达到90%的时候,CMS开始进行并发垃圾收集,于此同时,新生代还在迅速不断地晋升对象到年老代。当年老代CMS还未完成并发标记时,年老代满了,悲剧就发生了。CMS因为没内存可用不得不暂停mark,并触发一次stop the world(挂起所有jvm线程),然后采用单线程拷贝方式清理所有垃圾对象。这个过程会非常漫长。为了避免出现concurrent mode failed,建议让GC在未到90%时,就触发。
通过设置?-XX:CMSInitiatingOccupancyFraction=N
这个百分比, 可以简单的这么计算。如果你的?hfile.block.cache.size 和?hbase.regionserver.global.memstore.upperLimit 加起来有60%(默认),那么你可以设置 70-80,一般高10%左右差不多。
Hbase客户端优化
AutoFlush
将HTable的setAutoFlush设为false,可以支持客户端批量更新。即当Put填满客户端flush缓存时,才发送到服务端。
默认是true。
Scan Caching
scanner一次缓存多少数据来scan(从服务端一次抓多少数据回来scan)。
默认值是 1,一次只取一条。
Scan Attribute Selection
scan时建议指定需要的Column Family,减少通信量,否则scan操作默认会返回整个row的所有数据(所有Coulmn Family)。
Close ResultScanners
通过scan取完数据后,记得要关闭ResultScanner,否则RegionServer可能会出现问题(对应的Server资源无法释放)。
Optimal Loading of Row Keys
当你scan一张表的时候,返回结果只需要row key(不需要CF, qualifier,values,timestaps)时,你可以在scan实例中添加一个filterList,并设置 MUST_PASS_ALL操作,filterList中add?FirstKeyOnlyFilter或KeyOnlyFilter。这样可以减少网络通信量。
Turn off WAL on Puts
当Put某些非重要数据时,你可以设置writeToWAL(false),来进一步提高写性能。writeToWAL(false)会在Put时放弃写WAL log。风险是,当RegionServer宕机时,可能你刚才Put的那些数据会丢失,且无法恢复。
启用Bloom Filter
Bloom Filter通过空间换时间,提高读操作性能。
最后,感谢嬴北望同学对”hbase.hregion.memstore.flush.size”和“hbase.hstore.blockingStoreFiles”错误观点的修正。
hbase 优化 - 阿里古古 - ITeye技术网站
主要是从HBase应用程序设计与开发的角度,总结几种常用的性能优化方法。有关HBase系统配置级别的优化,这里涉及的不多,这部分可以参考:淘宝Ken Wu同学的博客。
1. 表的设计
1.1 Pre-Creating Regions
默认情况下,在创建HBase表的时候会自动创建一个region分区,当导入数据的时候,所有的HBase客户端都向这一个region写数据,直到这个region足够大了才进行切分。一种可以加快批量写入速度的方法是通过预先创建一些空的regions,这样当数据写入HBase时,会按照region分区情况,在集群内做数据的负载均衡。
有关预分区,详情参见:Table Creation: Pre-Creating Regions,下面是一个例子:
hbase shell:
create 'GidCross_Visit', 'gv', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
- public static boolean createTable(HBaseAdmin admin, HTableDescriptor table, byte[][] splits)
- throws IOException {
- try {
- admin.createTable(table, splits);
- return true;
- } catch (TableExistsException e) {
- logger.info("table " + table.getNameAsString() + " already exists");
- // the table already exists...
- return false;
- }
- }
- public static byte[][] getHexSplits(String startKey, String endKey, int numRegions) {
- byte[][] splits = new byte[numRegions-1][];
- BigInteger lowestKey = new BigInteger(startKey, 16);
- BigInteger highestKey = new BigInteger(endKey, 16);
- BigInteger range = highestKey.subtract(lowestKey);
- BigInteger regionIncrement = range.divide(BigInteger.valueOf(numRegions));
- lowestKey = lowestKey.add(regionIncrement);
- for(int i=0; i < numRegions-1;i++) {
- BigInteger key = lowestKey.add(regionIncrement.multiply(BigInteger.valueOf(i)));
- byte[] b = String.format("%016x", key).getBytes();
- splits[i] = b;
- }
- return splits;
- }
- public static byte[][] getHexSplits(List<String> regionStartKeyList) {
- if(regionStartKeyList ==null || regionStartKeyList.size()==0){
- return getHexSplits("0","FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",16);
- }else{
- byte[][] splits = new byte[regionStartKeyList.size()][];
- for (int i = 0; i <regionStartKeyList.size(); i++) {
- BigInteger key = new BigInteger(regionStartKeyList.get(i), 16);
- byte[] b = String.format("%016x", key).getBytes();
- splits[i] = b;
- }
- return splits;
- }
- }
1.2 Row Key
HBase中row key用来检索表中的记录,支持以下三种方式:
- 通过单个row key访问:即按照某个row key键值进行get操作;
- 通过row key的range进行scan:即通过设置startRowKey和endRowKey,在这个范围内进行扫描;
- 全表扫描:即直接扫描整张表中所有行记录。
在HBase中,row key可以是任意字符串,最大长度64KB,实际应用中一般为10~100bytes,存为byte[]字节数组,一般设计成定长的。
row key是按照字典序存储,因此,设计row key时,要充分利用这个排序特点,将经常一起读取的数据存储到一块,将最近可能会被访问的数据放在一块。
举个例子:如果最近写入HBase表中的数据是最可能被访问的,可以考虑将时间戳作为row key的一部分,由于是字典序排序,所以可以使用Long.MAX_VALUE – timestamp作为row key,这样能保证新写入的数据在读取时可以被快速命中。
1.3 Column Family
不要在一张表里定义太多的column family。目前Hbase并不能很好的处理超过2~3个column family的表。因为某个column family在flush的时候,它邻近的column family也会因关联效应被触发flush,最终导致系统产生更多的I/O。感兴趣的同学可以对自己的HBase集群进行实际测试,从得到的测试结果数据验证一下。
1.4 In Memory
创建表的时候,可以通过HColumnDescriptor.setInMemory(true)将表放到RegionServer的缓存中,保证在读取的时候被cache命中。
1.5 Max Version
创建表的时候,可以通过HColumnDescriptor.setMaxVersions(int maxVersions)设置表中数据的最大版本,如果只需要保存最新版本的数据,那么可以设置setMaxVersions(1)。
1.6 Time To Live
创建表的时候,可以通过HColumnDescriptor.setTimeToLive(int timeToLive)设置表中数据的存储生命期,过期数据将自动被删除,例如如果只需要存储最近两天的数据,那么可以设置setTimeToLive(2 * 24 * 60 * 60)。
1.7 Compact & Split
在HBase中,数据在更新时首先写入WAL 日志(HLog)和内存(MemStore)中,MemStore中的数据是排序的,当MemStore累计到一定阈值时,就会创建一个新的MemStore,并且将老的MemStore添加到flush队列,由单独的线程flush到磁盘上,成为一个StoreFile。于此同时, 系统会在zookeeper中记录一个redo point,表示这个时刻之前的变更已经持久化了(minor compact)。
StoreFile是只读的,一旦创建后就不可以再修改。因此Hbase的更新其实是不断追加的操作。当一个Store中的StoreFile达到一定的阈值后,就会进行一次合并(major compact),将对同一个key的修改合并到一起,形成一个大的StoreFile,当StoreFile的大小达到一定阈值后,又会对 StoreFile进行分割(split),等分为两个StoreFile。
由于对表的更新是不断追加的,处理读请求时,需要访问Store中全部的StoreFile和MemStore,将它们按照row key进行合并,由于StoreFile和MemStore都是经过排序的,并且StoreFile带有内存中索引,通常合并过程还是比较快的。
实际应用中,可以考虑必要时手动进行major compact,将同一个row key的修改进行合并形成一个大的StoreFile。同时,可以将StoreFile设置大些,减少split的发生。
2. 写表操作
2.1 多HTable并发写
创建多个HTable客户端用于写操作,提高写数据的吞吐量,一个例子:
- static final Configuration conf = HBaseConfiguration.create();
- static final String table_log_name = “user_log”;
- wTableLog = new HTable[tableN];
- for (int i = 0; i < tableN; i++) {
- wTableLog[i] = new HTable(conf, table_log_name);
- wTableLog[i].setWriteBufferSize(5 * 1024 * 1024); //5MB
- wTableLog[i].setAutoFlush(false);
- }
2.2 HTable参数设置
2.2.1 Auto Flush
通过调用HTable.setAutoFlush(false)方法可以将HTable写客户端的自动flush关闭,这样可以批量写入数据到HBase,而不是有一条put就执行一次更新,只有当put填满客户端写缓存时,才实际向HBase服务端发起写请求。默认情况下auto flush是开启的。
2.2.2 Write Buffer
通过调用HTable.setWriteBufferSize(writeBufferSize)方法可以设置HTable客户端的写buffer大小,如果新设置的buffer小于当前写buffer中的数据时,buffer将会被flush到服务端。其中,writeBufferSize的单位是byte字节数,可以根据实际写入数据量的多少来设置该值。
2.2.3 WAL Flag
在HBae中,客户端向集群中的RegionServer提交数据时(Put/Delete操作),首先会先写WAL(Write Ahead Log)日志(即HLog,一个RegionServer上的所有Region共享一个HLog),只有当WAL日志写成功后,再接着写MemStore,然后客户端被通知提交数据成功;如果写WAL日志失败,客户端则被通知提交失败。这样做的好处是可以做到RegionServer宕机后的数据恢复。
因此,对于相对不太重要的数据,可以在Put/Delete操作时,通过调用Put.setWriteToWAL(false)或Delete.setWriteToWAL(false)函数,放弃写WAL日志,从而提高数据写入的性能。
值得注意的是:谨慎选择关闭WAL日志,因为这样的话,一旦RegionServer宕机,Put/Delete的数据将会无法根据WAL日志进行恢复。
2.3 批量写
通过调用HTable.put(Put)方法可以将一个指定的row key记录写入HBase,同样HBase提供了另一个方法:通过调用HTable.put(List<Put>)方法可以将指定的row key列表,批量写入多行记录,这样做的好处是批量执行,只需要一次网络I/O开销,这对于对数据实时性要求高,网络传输RTT高的情景下可能带来明显的性能提升。
2.4 多线程并发写
在客户端开启多个HTable写线程,每个写线程负责一个HTable对象的flush操作,这样结合定时flush和写buffer(writeBufferSize),可以既保证在数据量小的时候,数据可以在较短时间内被flush(如1秒内),同时又保证在数据量大的时候,写buffer一满就及时进行flush。下面给个具体的例子:
- for (int i = 0; i < threadN; i++) {
- Thread th = new Thread() {
- public void run() {
- while (true) {
- try {
- sleep(1000); //1 second
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- synchronized (wTableLog[i]) {
- try {
- wTableLog[i].flushCommits();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
- };
- th.setDaemon(true);
- th.start();
- }
3. 读表操作
3.1 多HTable并发读
创建多个HTable客户端用于读操作,提高读数据的吞吐量,一个例子:
|
1
2
3
4
5
6
7
|
static final Configuration conf = HBaseConfiguration.create();static final String table_log_name = “user_log”;rTableLog = new HTable[tableN];for (int i = 0; i < tableN; i++) { rTableLog[i] = new HTable(conf, table_log_name); rTableLog[i].setScannerCaching(50);} |
3.2 HTable参数设置
3.2.1 Scanner Caching
通过调用HTable.setScannerCaching(int scannerCaching)可以设置HBase scanner一次从服务端抓取的数据条数,默认情况下一次一条。通过将此值设置成一个合理的值,可以减少scan过程中next()的时间开销,代价是scanner需要通过客户端的内存来维持这些被cache的行记录。
3.2.2 Scan Attribute Selection
scan时指定需要的Column Family,可以减少网络传输数据量,否则默认scan操作会返回整行所有Column Family的数据。
3.2.3 Close ResultScanner
通过scan取完数据后,记得要关闭ResultScanner,否则RegionServer可能会出现问题(对应的Server资源无法释放)。
3.3 批量读
通过调用HTable.get(Get)方法可以根据一个指定的row key获取一行记录,同样HBase提供了另一个方法:通过调用HTable.get(List)方法可以根据一个指定的row key列表,批量获取多行记录,这样做的好处是批量执行,只需要一次网络I/O开销,这对于对数据实时性要求高而且网络传输RTT高的情景下可能带来明显的性能提升。
3.4 多线程并发读
在客户端开启多个HTable读线程,每个读线程负责通过HTable对象进行get操作。下面是一个多线程并发读取HBase,获取店铺一天内各分钟PV值的例子:
- public class DataReaderServer {
- //获取店铺一天内各分钟PV值的入口函数
- public static ConcurrentHashMap getUnitMinutePV(long uid, long startStamp, long endStamp){
- long min = startStamp;
- int count = (int)((endStamp - startStamp) / (60*1000));
- List lst = new ArrayList();
- for (int i = 0; i <= count; i++) {
- min = startStamp + i * 60 * 1000;
- lst.add(uid + "_" + min);
- }
- return parallelBatchMinutePV(lst);
- }
- //多线程并发查询,获取分钟PV值
- private static ConcurrentHashMap parallelBatchMinutePV(List lstKeys){
- ConcurrentHashMap hashRet = new ConcurrentHashMap();
- int parallel = 3;
- List<List<String>> lstBatchKeys = null;
- if (lstKeys.size() < parallel ){
- lstBatchKeys = new ArrayList<List<String>>(1);
- lstBatchKeys.add(lstKeys);
- }
- else{
- lstBatchKeys = new ArrayList<List<String>>(parallel);
- for(int i = 0; i < parallel; i++ ){
- List lst = new ArrayList();
- lstBatchKeys.add(lst);
- }
- for(int i = 0 ; i < lstKeys.size() ; i ++ ){
- lstBatchKeys.get(i%parallel).add(lstKeys.get(i));
- }
- }
- List >> futures = new ArrayList >>(5);
- ThreadFactoryBuilder builder = new ThreadFactoryBuilder();
- builder.setNameFormat("ParallelBatchQuery");
- ThreadFactory factory = builder.build();
- ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(lstBatchKeys.size(), factory);
- for(List keys : lstBatchKeys){
- Callable< ConcurrentHashMap > callable = new BatchMinutePVCallable(keys);
- FutureTask< ConcurrentHashMap > future = (FutureTask< ConcurrentHashMap >) executor.submit(callable);
- futures.add(future);
- }
- executor.shutdown();
- // Wait for all the tasks to finish
- try {
- boolean stillRunning = !executor.awaitTermination(
- 5000000, TimeUnit.MILLISECONDS);
- if (stillRunning) {
- try {
- executor.shutdownNow();
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- } catch (InterruptedException e) {
- try {
- Thread.currentThread().interrupt();
- } catch (Exception e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- }
- // Look for any exception
- for (Future f : futures) {
- try {
- if(f.get() != null)
- {
- hashRet.putAll((ConcurrentHashMap)f.get());
- }
- } catch (InterruptedException e) {
- try {
- Thread.currentThread().interrupt();
- } catch (Exception e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
- return hashRet;
- }
- //一个线程批量查询,获取分钟PV值
- protected static ConcurrentHashMap getBatchMinutePV(List lstKeys){
- ConcurrentHashMap hashRet = null;
- List lstGet = new ArrayList();
- String[] splitValue = null;
- for (String s : lstKeys) {
- splitValue = s.split("_");
- long uid = Long.parseLong(splitValue[0]);
- long min = Long.parseLong(splitValue[1]);
- byte[] key = new byte[16];
- Bytes.putLong(key, 0, uid);
- Bytes.putLong(key, 8, min);
- Get g = new Get(key);
- g.addFamily(fp);
- lstGet.add(g);
- }
- Result[] res = null;
- try {
- res = tableMinutePV[rand.nextInt(tableN)].get(lstGet);
- } catch (IOException e1) {
- logger.error("tableMinutePV exception, e=" + e1.getStackTrace());
- }
- if (res != null && res.length > 0) {
- hashRet = new ConcurrentHashMap(res.length);
- for (Result re : res) {
- if (re != null && !re.isEmpty()) {
- try {
- byte[] key = re.getRow();
- byte[] value = re.getValue(fp, cp);
- if (key != null && value != null) {
- hashRet.put(String.valueOf(Bytes.toLong(key,
- Bytes.SIZEOF_LONG)), String.valueOf(Bytes
- .toLong(value)));
- }
- } catch (Exception e2) {
- logger.error(e2.getStackTrace());
- }
- }
- }
- }
- return hashRet;
- }
- }
- //调用接口类,实现Callable接口
- class BatchMinutePVCallable implements Callable>{
- private List keys;
- public BatchMinutePVCallable(List lstKeys ) {
- this.keys = lstKeys;
- }
- public ConcurrentHashMap call() throws Exception {
- return DataReadServer.getBatchMinutePV(keys);
- }
- }
3.5 缓存查询结果
对于频繁查询HBase的应用场景,可以考虑在应用程序中做缓存,当有新的查询请求时,首先在缓存中查找,如果存在则直接返回,不再查询HBase;否则对HBase发起读请求查询,然后在应用程序中将查询结果缓存起来。至于缓存的替换策略,可以考虑LRU等常用的策略。
3.6 Blockcache
HBase上Regionserver的内存分为两个部分,一部分作为Memstore,主要用来写;另外一部分作为BlockCache,主要用于读。
写请求会先写入Memstore,Regionserver会给每个region提供一个Memstore,当Memstore满64MB以后,会启动 flush刷新到磁盘。当Memstore的总大小超过限制时(heapsize * hbase.regionserver.global.memstore.upperLimit * 0.9),会强行启动flush进程,从最大的Memstore开始flush直到低于限制。
读请求先到Memstore中查数据,查不到就到BlockCache中查,再查不到就会到磁盘上读,并把读的结果放入BlockCache。由于BlockCache采用的是LRU策略,因此BlockCache达到上限(heapsize * hfile.block.cache.size * 0.85)后,会启动淘汰机制,淘汰掉最老的一批数据。
一个Regionserver上有一个BlockCache和N个Memstore,它们的大小之和不能大于等于heapsize * 0.8,否则HBase不能启动。默认BlockCache为0.2,而Memstore为0.4。对于注重读响应时间的系统,可以将 BlockCache设大些,比如设置BlockCache=0.4,Memstore=0.39,以加大缓存的命中率。
有关BlockCache机制,请参考这里:HBase的Block cache,HBase的blockcache机制,hbase中的缓存的计算与使用。
4.数据计算
4.1 服务端计算
Coprocessor运行于HBase RegionServer服务端,各个Regions保持对与其相关的coprocessor实现类的引用,coprocessor类可以通过RegionServer上classpath中的本地jar或HDFS的classloader进行加载。
目前,已提供有几种coprocessor:
Coprocessor:提供对于region管理的钩子,例如region的open/close/split/flush/compact等;
RegionObserver:提供用于从客户端监控表相关操作的钩子,例如表的get/put/scan/delete等;
Endpoint:提供可以在region上执行任意函数的命令触发器。一个使用例子是RegionServer端的列聚合,这里有代码示例。
以上只是有关coprocessor的一些基本介绍,本人没有对其实际使用的经验,对它的可用性和性能数据不得而知。感兴趣的同学可以尝试一下,欢迎讨论。
4.2 写端计算
4.2.1 计数
HBase本身可以看作是一个可以水平扩展的Key-Value存储系统,但是其本身的计算能力有限(Coprocessor可以提供一定的服务端计算),因此,使用HBase时,往往需要从写端或者读端进行计算,然后将最终的计算结果返回给调用者。举两个简单的例子:
PV计算:通过在HBase写端内存中,累加计数,维护PV值的更新,同时为了做到持久化,定期(如1秒)将PV计算结果同步到HBase中,这样查询端最多会有1秒钟的延迟,能看到秒级延迟的PV结果。
分钟PV计算:与上面提到的PV计算方法相结合,每分钟将当前的累计PV值,按照rowkey + minute作为新的rowkey写入HBase中,然后在查询端通过scan得到当天各个分钟以前的累计PV值,然后顺次将前后两分钟的累计PV值相减,就得到了当前一分钟内的PV值,从而最终也就得到当天各个分钟内的PV值。
4.2.2 去重
对于UV的计算,就是个去重计算的例子。分两种情况:
如果内存可以容纳,那么可以在Hash表中维护所有已经存在的UV标识,每当新来一个标识时,通过快速查找Hash确定是否是一个新的UV,若是则UV值加1,否则UV值不变。另外,为了做到持久化或提供给查询接口使用,可以定期(如1秒)将UV计算结果同步到HBase中。
如果内存不能容纳,可以考虑采用Bloom Filter来实现,从而尽可能的减少内存的占用情况。除了UV的计算外,判断URL是否存在也是个典型的应用场景。
4.3 读端计算
如果对于响应时间要求比较苛刻的情况(如单次http请求要在毫秒级时间内返回),个人觉得读端不宜做过多复杂的计算逻辑,尽量做到读端功能单一化:即从HBase RegionServer读到数据(scan或get方式)后,按照数据格式进行简单的拼接,直接返回给前端使用。当然,如果对于响应时间要求一般,或者业务特点需要,也可以在读端进行一些计算逻辑。
5.总结
作为一个Key-Value存储系统,HBase并不是万能的,它有自己独特的地方。因此,基于它来做应用时,我们往往需要从多方面进行优化改进(表设计、读表操作、写表操作、数据计算等),有时甚至还需要从系统级对HBase进行配置调优,更甚至可以对HBase本身进行优化。这属于不同的层次范畴。
总之,概括来讲,对系统进行优化时,首先定位到影响你的程序运行性能的瓶颈之处,然后有的放矢进行针对行的优化。如果优化后满足你的期望,那么就可以停止优化;否则继续寻找新的瓶颈之处,开始新的优化,直到满足性能要求。
【3】Hadoop中常出现的错误以及解决方法 - 数据库 - Tech - ITeye论坛
1:Shuffle Error: Exceeded MAX_FAILED_UNIQUE_FETCHES; bailing-out
Answer:
程序里面需要打开多个文件,进行分析,系统一般默认数量是1024,(用ulimit -a可以看到)对于正常使用是够了,但是对于程序来讲,就太少了。
修改办法:
修改2个文件。
/etc/security/limits.conf
vi /etc/security/limits.conf
加上:
* soft nofile 102400
* hard nofile 409600
$cd /etc/pam.d/
$sudo vi login
添加 session required /lib/security/pam_limits.so
2:Too many fetch-failures
Answer:
出现这个问题主要是结点间的连通不够全面。
1) 检查 、/etc/hosts
要求本机ip 对应 服务器名
要求要包含所有的服务器ip + 服务器名
2) 检查 .ssh/authorized_keys
要求包含所有服务器(包括其自身)的public key
3:处理速度特别的慢 出现map很快 但是reduce很慢 而且反复出现 reduce=0%
Answer:
结合第二点,然后
修改 conf/hadoop-env.sh 中的export HADOOP_HEAPSIZE=4000
4:能够启动datanode,但无法访问,也无法结束的错误
在重新格式化一个新的分布式文件时,需要将你NameNode上所配置的dfs.name.dir这一namenode用来存放NameNode 持久存储名字空间及事务日志的本地文件系统路径删除,同时将各DataNode上的dfs.data.dir的路径 DataNode 存放块数据的本地文件系统路径的目录也删除。如本此配置就是在NameNode上删除/home/hadoop/NameData,在DataNode上删除/home/hadoop/DataNode1和/home/hadoop/DataNode2。这是因为Hadoop在格式化一个新的分布式文件系统时,每个存储的名字空间都对应了建立时间的那个版本(可以查看/home/hadoop /NameData/current目录下的VERSION文件,上面记录了版本信息),在重新格式化新的分布式系统文件时,最好先删除NameData 目录。必须删除各DataNode的dfs.data.dir。这样才可以使namedode和datanode记录的信息版本对应。
注意:删除是个很危险的动作,不能确认的情况下不能删除!!做好删除的文件等通通备份!!
5:java.io.IOException: Could not obtain block: blk_194219614024901469_1100 file=/user/hive/warehouse/src_20090724_log/src_20090724_log
出现这种情况大多是结点断了,没有连接上。
6:java.lang.OutOfMemoryError: Java heap space
出现这种异常,明显是jvm内存不够得原因,要修改所有的datanode的jvm内存大小。
Java -Xms1024m -Xmx4096m
一般jvm的最大内存使用应该为总内存大小的一半,我们使用的8G内存,所以设置为4096m,这一值可能依旧不是最优的值。(其实对于最好设置为真实物理内存大小的0.8)
7:出现map%,但是呢reduce到98%左右的时候呢,就直接进failedjobs了
解决办法:
检查mapred.map.tasks是不是设置的太多了,设置太多的话会导致处理大量的小文件
检查mapred.reduce.parallel.copies是否设置合适。
8:
系统根目录下的/tmp文件夹是不可以删除的
否则bin/hadoop jps
会出现异常:
Exception in thread "main" java.lang.NullPointerException at sun.jvmstat.perfdata.monitor.protocol.local.LocalVmManager.activeVms(LocalVmManager.java:127)
at sun.jvmstat.perfdata.monitor.protocol.local.MonitoredHostProvider.activeVms(MonitoredHostProvider.java:133)
at sun.tools.jps.Jps.main(Jps.java:45)
同时
bin/hive
Unable to create log directory /tmp/hadoopuser
2:Too many fetch-failures
Answer:
出现这个问题主要是结点间的连通不够全面。
1) 检查 、/etc/hosts
要求本机ip 对应 服务器名
要求要包含所有的服务器ip + 服务器名
2) 检查 .ssh/authorized_keys
要求包含所有服务器(包括其自身)的public key
3:处理速度特别的慢 出现map很快 但是reduce很慢 而且反复出现 reduce=0%
Answer:
结合第二点,然后
修改 conf/hadoop-env.sh 中的export HADOOP_HEAPSIZE=4000
4:能够启动datanode,但无法访问,也无法结束的错误
在重新格式化一个新的分布式文件时,需要将你NameNode上所配置的dfs.name.dir这一namenode用来存放NameNode 持久存储名字空间及事务日志的本地文件系统路径删除,同时将各DataNode上的dfs.data.dir的路径 DataNode 存放块数据的本地文件系统路径的目录也删除。如本此配置就是在NameNode上删除/home/hadoop/NameData,在DataNode上删除/home/hadoop/DataNode1和/home/hadoop/DataNode2。这是因为Hadoop在格式化一个新的分布式文件系统时,每个存储的名字空间都对应了建立时间的那个版本(可以查看/home/hadoop /NameData/current目录下的VERSION文件,上面记录了版本信息),在重新格式化新的分布式系统文件时,最好先删除NameData 目录。必须删除各DataNode的dfs.data.dir。这样才可以使namedode和datanode记录的信息版本对应。
注意:删除是个很危险的动作,不能确认的情况下不能删除!!做好删除的文件等通通备份!!
5:java.io.IOException: Could not obtain block: blk_194219614024901469_1100 file=/user/hive/warehouse/src_20090724_log/src_20090724_log
出现这种情况大多是结点断了,没有连接上。
6:java.lang.OutOfMemoryError: Java heap space
出现这种异常,明显是jvm内存不够得原因,要修改所有的datanode的jvm内存大小。
Java -Xms1024m -Xmx4096m
一般jvm的最大内存使用应该为总内存大小的一半,我们使用的8G内存,所以设置为4096m,这一值可能依旧不是最优的值。(其实对于最好设置为真实物理内存大小的0.8)
7:出现map%,但是呢reduce到98%左右的时候呢,就直接进failedjobs了
解决办法:
检查mapred.map.tasks是不是设置的太多了,设置太多的话会导致处理大量的小文件
检查mapred.reduce.parallel.copies是否设置合适。
8:
系统根目录下的/tmp文件夹是不可以删除的
否则bin/hadoop jps
会出现异常:
Exception in thread "main" java.lang.NullPointerException at sun.jvmstat.perfdata.monitor.protocol.local.LocalVmManager.activeVms(LocalVmManager.java:127)
at sun.jvmstat.perfdata.monitor.protocol.local.MonitoredHostProvider.activeVms(MonitoredHostProvider.java:133)
at sun.tools.jps.Jps.main(Jps.java:45)
同时
bin/hive
Unable to create log directory /tmp/hadoopuser
2:Too many fetch-failures
Answer:
出现这个问题主要是结点间的连通不够全面。
1) 检查 、/etc/hosts
要求本机ip 对应 服务器名
要求要包含所有的服务器ip + 服务器名
2) 检查 .ssh/authorized_keys
要求包含所有服务器(包括其自身)的public key
3:处理速度特别的慢 出现map很快 但是reduce很慢 而且反复出现 reduce=0%
Answer:
结合第二点,然后
修改 conf/hadoop-env.sh 中的export HADOOP_HEAPSIZE=4000
4:能够启动datanode,但无法访问,也无法结束的错误
在重新格式化一个新的分布式文件时,需要将你NameNode上所配置的dfs.name.dir这一namenode用来存放NameNode 持久存储名字空间及事务日志的本地文件系统路径删除,同时将各DataNode上的dfs.data.dir的路径 DataNode 存放块数据的本地文件系统路径的目录也删除。如本此配置就是在NameNode上删除/home/hadoop/NameData,在DataNode上删除/home/hadoop/DataNode1和/home/hadoop/DataNode2。这是因为Hadoop在格式化一个新的分布式文件系统时,每个存储的名字空间都对应了建立时间的那个版本(可以查看/home/hadoop /NameData/current目录下的VERSION文件,上面记录了版本信息),在重新格式化新的分布式系统文件时,最好先删除NameData 目录。必须删除各DataNode的dfs.data.dir。这样才可以使namedode和datanode记录的信息版本对应。
注意:删除是个很危险的动作,不能确认的情况下不能删除!!做好删除的文件等通通备份!!
5:java.io.IOException: Could not obtain block: blk_194219614024901469_1100 file=/user/hive/warehouse/src_20090724_log/src_20090724_log
出现这种情况大多是结点断了,没有连接上。
6:java.lang.OutOfMemoryError: Java heap space
出现这种异常,明显是jvm内存不够得原因,要修改所有的datanode的jvm内存大小。
Java -Xms1024m -Xmx4096m
一般jvm的最大内存使用应该为总内存大小的一半,我们使用的8G内存,所以设置为4096m,这一值可能依旧不是最优的值。(其实对于最好设置为真实物理内存大小的0.8)
7:出现map%,但是呢reduce到98%左右的时候呢,就直接进failedjobs了
解决办法:
检查mapred.map.tasks是不是设置的太多了,设置太多的话会导致处理大量的小文件
检查mapred.reduce.parallel.copies是否设置合适。
8:
系统根目录下的/tmp文件夹是不可以删除的
(jps is based on jvmstat and it needs to be able to secure a memory mapped file on the temporary file system.
)
否则bin/hadoop jps
会出现异常:
Exception in thread "main" java.lang.NullPointerException at sun.jvmstat.perfdata.monitor.protocol.local.LocalVmManager.activeVms(LocalVmManager.java:127)
at sun.jvmstat.perfdata.monitor.protocol.local.MonitoredHostProvider.activeVms(MonitoredHostProvider.java:133)
at sun.tools.jps.Jps.main(Jps.java:45)
同时
bin/hive
Unable to create log directory /tmp/hadoopuser
从HTML文件中抽取正文的简单方案 试验结果 - hzxdark - ITeye技术网站
一、 简介
本文是根据alexjc的<The Easy Way to Extract Useful Text from Arbitrary HTML>一文进行实验的结果。原文见:
http://ai-depot.com/articles/the-easy-way-to-extract-useful-text-from-arbitrary-html/
——alexjc原文
http://blog.csdn.net/lanphaday/archive/2007/08/13/1741185.aspx
——恋花蝶翻译的中英对照版本
该文章主要内容是讲述如何利用正文相对于其他文本,正文文本与生成该正文所需的html字节码的比值较大的规律,利用神经网络识别出正文过滤过滤广告的效果。主要设计如下:
1. 解析HTML代码并记下处理的字节数。
2. 以行或段的形式保存解析输出的文本。
3. 统计每一行文本相应的HTML代码的字节数
4. 通过计算文本相对于字节数的比率来获取文本密度
5. 最后用神经网络来决定这一行是不是正文的一部分。
二、 设计方案
本实验相对原本alexjc设计方案有几点修改:
1. 用RPROP(弹性BP网络)代替原文的感知器;
2. 由于原文并没有把文本长度、html字节长度做归一化,所以不采用原始文本长度、html字节长度作为特征值。相对的,对归一化后的文本长度、html字节长度,以及前向后向N行等各种组合进行试验。
3. 试验文本为任意在网上选取的10个网页,见附件。
4. 原文并没有提及,如何定义一行文本是否正文,所以这里定义了几个正文类型:
a) 内容型正文,特征是有长的连续文字段,定义这些文字段为正文;
b) 论坛型,有短的不连续的文字段,定义这些文字段为正文;
c) 论坛帖子列表型(部分试验将会对这类型进行训练查看效果,对于论坛帖子列表是否属于正文这里不做讨论……),帖子标题为正文;
d) 首页型,定义为没有正文(厄,谁能说出,新浪首页哪些是正文?)
实验环境:
1. 语言:JAVA,JRE1.5
2. 操作系统:windows xp
三、 实验过程:
1. 设计实现一个三层RPROP网络(令人惊讶的是,居然在这个领域没有人写一个开源的组件,apache等的开源巨头们都对neural network不感兴趣么?)。
/*
*初始化RPROP对象
*
*本函数用于创建训练前的RPROP对象
*参数:
* int in_num 输入层个数;
* int hidden_unit_num 隐含层节点个数
* int out_num 输出层个数
*
*/
public RPROP(int in_num, int hidden_unit_num, int out_num)
/*
*初始化RPROP对象
*
*本函数用于创建训练后的RPROP对象
*参数:
* int in_num 输入层个数;
* int hidden_unit_num 隐含层节点个数
* int out_num 输出层个数
* double[][] w1 隐含层权重
* double[][] w2 输出层权重
* double[] b1 隐含层偏离值
* double[] b2 输出层偏离值
*/
public RPROP(int in_num, int hidden_unit_num, int out_num, double[][] w1, double[][] w2, double[] b1, double[] b2)
/*
*计算输出结果
*
*参数:
* double[] p 输入参数
*返回值:
* double[] 输出结果
*/
public double[] output(double[] p)
/*
*训练
*
*参数:
* double[][] p
* 训练样本集
* double[][][] t
* 期望结果集, t[i][j][0] 期望结果, t[i][j][1]误差放大系数
* double goal
* 目标误差,注意,本网络用的是“方差”作为误差判断条件
* int epochs
* 训练最大次数
*/
public void train(double[][] p, double[][][] t, double goal,int epochs)
对于这个实现,有兴趣的朋友在本文最后下载附件。
2. 选取特征值
在实验中,笔者尝试了各种特征值组合:
1) 文本密度,文本长度,html字节码长度,前后各一行的同样数值;(原文设定)
2) 文本密度,文本长度倒数(归一化),前后各两行的同样数值;
3) 文本所在的html的链接密度(全文文本长度/总链接数,用于加强判断文本类型),文本密度,文本长度/5000(归一化,大于1的当1处理,下文简称为文本长度2),前后两行相同的数值;
4) 文本所在的html的链接密度,文本密度,文本长度2,前后两行相同的数值;
5) 文本所在的html的链接密度,文本密度,文本长度2,前后一行相同的数值;
6) 文本所在的html的链接密度,文本密度,文本长度2,前一行是否正文;
并规定,网络输出结果0为非正文,1为正文。
在训练过程中,发现训练过的网络命中率大部分落在0值部分,这是由于论坛这种短文段类型的网页会导致0值过多,训练时对0值过拟合。为了避免这一点,对某一篇网页的某一行的误差乘以该网页的0值与1值数量的比值。
3. 训练集获取
见附件。这是在笔者常浏览的网页中任意抽取的10个网页。对于期望输出的定义见上文。
四、实验结果
1. 1~5的实验,任意抽取部分样本集作为训练集,对于训练集拟合的很好,但对于测试集的表现却非常糟糕(请原谅笔者并没有记录实验数据);
这部分结果表明,以文本密度作为判断是否正文的特征值是有问题的。观察样本集的数据可以发现,即使是内容型的大段文字,也有可能文本密度很低——为了让网页变得更漂亮美观,现在有很多网站都对文字内容加了大段大段修饰用html代码……
鉴于这一点,笔者最终放弃文本密度作为特征值。而考虑到广告都是带链接的文本,相对的正文连接数则比较少,所以笔者认为,用文本长度/链接数 作为特征值或许会是一个更好的选择。
2. 6的实验,表现意外的非常的好(好到差点让笔者以为终于找到完美的解决方案……)
确实,即使是在测试集部分的表现也惊人好,但实际上有一个问题:每一行的计算受上一行计算的结果影响。测试集是事先定义每一行的上一行的结果,但在实际使用时,上一行的结果是实时计算出来的,所以就会出现,在某一行出错,导致后面的结果全部出错的情况……
至此,假如仍然坚持神经网络的解决方案,或许,采用:
文本长度,文本长度链接数,上一行的结果 做特征值, 采用三个弱分类器的ada-boost组合分类或许会是一个好的选择。
除此之外,实际上对正文的定义对结果也是有很大的影响。实际上,假如能根据数据化的东西定义某一个类别,那么对于该类别的划分,或许其实已经是可预知的,不如直接设计阈值处理。
笔者的实验则到此为止,并放弃了神经网络这个解决方案——直接采用这些特征值进行阈值判断,并对一些特殊部分设定过滤规则,这似乎比神经网络的表现来的简单、有效……
如果有哪位朋友感兴趣,并用ada-boost进行实验,笔者将非常期待这位朋友来交流下心得:)
附件:
neralNetwork.rar 源代码
res.rar 训练集
关于html文本抽取部分,这里用的是HtmlParser,这里修改的代码就不贴出来了,有兴趣的朋友可以去:
http://htmlparser.sourceforge.net/
看看。
目前互联网上公布出来的正文提取算法,大家可以综合比较下,一起来测试下哪个更好用。 词网--北京词网科技有限公司 http://demo.cikuu.com/cgi-bin/cgi-contex 猎兔网页正文提取 http://www.lietu.com/extract/ PHP版网页正文提取 http://www.woniu.us/get_content_demo/ 网页正文提取分析(DEMO) http://61.128.196.27/txt 个人认为http://61.128.196.27/txt 这个提取最牛,基本上无论什么页面都能提取出来,而且能有效的保持原文风格、图片、链接。
http://code.google.com/p/joyhtml/
看看这个效果不错
http://www.likeshow.net/article.asp?id=92
我一年前写的玩意 虽然不完善 但尚可用之在新闻和BLOG 论坛提取上 提取的正文对于BLOG和BBS包含评论及回复 具体原理也写很清楚了
如题,想从html源码中提取正文内容,<P></P>之间的内容,但是<P>的写法不规则。除了正则表达式的方法,还有其它的提取方法吗?谢谢!
最新下载
在线演示和最新下载:
http://www.shoula.net/ParseContent
http://www.pudn.com/downloads152/sourcecode/internet/search_engine/detail668443.html
Google Code开源网页正文提取cx-extractor2010-05-19 12:31基于行块分布函数的通用网页正文抽取:线性时间、不建DOM树、与HTML标签无关
简述:
对于Web信息检索来说,网页正文抽取是后续处理的关键。虽然使用正则表达式可以准确的抽取某一固定格式的页面,但面对形形色色的HTML,使用规则处理难免捉襟见肘。能不能高效、准确的将一个页面的正文抽取出来,并做到在大规模网页范围内通用,这是一个直接关系上层应用的难题。
作者提出了《基于行块分布函数的通用网页正文抽取算法》,首次将网页正文抽取问题转化为求页面的行块分布函数,这种方法不用建立Dom树,不被病态HTML所累(事实上与HTML标签完全无关)。通过在线性时间内建立的行块分布函数图,直接准确定位网页正文。同时采用了统计与规则相结合的方法来处理通用性问题。作者相信简单的事情总应该用最简单的办法来解决这一亘古不变的道理。整个算法实现不足百行代码。但量不在多,在法。
项目网址:http://code.google.com/p/cx-extractor/
算法描述:基于行块分布函数的网页正文抽取算法.pdf
欢迎大家提出意见~
http://www.ngiv.cn/post/204.html
VIPS算法对搜索引擎的意义
http://blog.csdn.net/tingya/archive/2006/02/18/601954.aspx
基于视觉的Web页面分页算法VIPS的实现源代码下载
http://blog.csdn.net/tingya/archive/2006/04/28/694651.aspx
作者信息:飞跃,javascript教程-技术之家博客的博主
http://www.madcn.net/?p=791
我这里有个开源的项目,还不错,你上googlecode搜索joyhtml。
http://gfnpad.blogspot.com/2009/11/blog-post.html
下面几个是一些开源的程序:
1.一个python的基于文本密度的程序:
http://ai-depot.com/articles/the-easy-way-to-extract-useful-text-from-arbitrary-html/
ps:里面有bug,要稍加改动。 另外,对于没有对html注释部分进行处理
2.Java 开源项目: Gate
http://gate.ac.uk/
其实可以利用Dhmtl对象进行编程分析,已获得所要的数据文件,详细请看我的程序
http://www.vbgood.com/thread-94788-1-1.html
http://download.csdn.net/source/568439
一.标题块
l 分块节点:td,div,h,span
l 一般位于Head/Title的位置
l 当前单元含有<h1>-<h3>,<b>,<i>,<strong>等标签
l 样式,一般class包含title,head等字符
l 文字长度,一般大于3个字符,小于35个字符
二.发表时间块
l 分块节点:td,div, span
l 文字长度,一般小于50个字符
l 包含日期格式(2010-08-09)的字符串
l 包含以下关键字:来源,发表
三.主题块
l 分块节点:td,div
l HTML网页中有一些特殊标签,通常只出现在网页主题块中,如<P><BR>等。因此,主题块中往往包含着特殊标签。
l 主题块内容含有较多的句子,因此具有较多逗号、句号等标点符号(>5)。
l 若从信息量角度考虑,主题块一般是含有较多文字信息。
l 主题块的 标签密度=1000*标签数/文字数 应在小于一个范围。
l 主题块的 文本密度=len(文本)/len(HTML代码) 较大
l 不应该包含 “上一篇”,“下一篇”
l 包含以下字符串的内容块,判定为包含版权信息,需减权:“ICP备04000001号”,“版权所有”,“Copyright”
l 主题块序号在标题块之下
l 主题块序号在发表时间块之下
l 主题块序号在相关链接块之上
四.相关链接块
l 分块节点:td,div
l 文字应为“相关链接”、“相关新闻”、“相关报道”等敏感词,且连接比例很高。
l 链接数小于20
实现:
根据以上信息块特征,采用特征提权算法,C#(3.5)编程实现,命名为QD正文提取组件。经测试,对Html格式规范的以文字为主的内容页,正确提取率在85%以上,各大门户的新闻页面在95%以上。 例子下载(需要安装Microsoft .NET Framework 3.5)
注:QD正文提取组件 不开源,需要源码的朋友可选择付费获取。
这时挑选出的正文一般也就是到位了,但是问题是很可能在头尾残留了一些块广告。我认为这些块广告与正文中广告有很大的不同。这些广告的马脚就是其父节点,它们的父节点要么也包含了正文所在区域,也就是和正文平级,要么本身就是正文所在区域的一个子节点,很难是正文节点本身的。那么对疑似正文节点进行一次扫描,剔除那些父节点文字内容过大(包含了广告以及正文,即和正文平级)的块,也剔除那些父节点文字内容过小的块。
经过这样的处理,得到的内容基本上就是我们需要的正文了。下面就是要提取标题。
在代表整个网页的document中扫描一次,寻找那些有font字体的,strong的,h1的,title的节点,提取他们的信息。然后将得到的文字内容分词,查验分出来的词有多少是被正文包含的,包含最多的一半就是标题。但是这里要注意,有时候找到的节点本身是正文节点的子节点,那么无论怎么分,分出来都是完全包含的,所以要剔除那些本身是正文一部分的疑似标题。这样做对大部分网页也是有效了,但是对仅有的标题就在正文节点里的那些页面,目前为止我还没有特别好的想法。
这些日子也研究了一些别人的论文,有很多思想都非常好,也有很多人想到用马尔科夫,人工神经来训练。也许以后我会考虑用用看吧。现在这样也还可以,呵呵。
?
这个算法我也写了一下,不过是用C++写的。
我不太懂楼上讨论的分页是什么意思,我通过分析dom树然后用文中提到的规则进行dom结点处理以及后续的处理。
我主要是想把网页中的内容按网页框架分开,把正文部分合在一起,然后用贝叶斯决策计算正文特征支持率
提取网页内容。
现在VIPS基本写完。
但是却也发现了些问题,
比如说有些结点的坐标提取出来会有提取不出分隔条,这是因为有少数坐标有些重叠。这里涉及到一个坐标的确定问题。
然后是结点分割规则问题,现在的页面是大部分是通过DIV来组织页面。而VIPS似乎更合适TABLE组织的页面,我试过用TABLE组织的页面,分得相当不错。
另外,TINYA上面的翻译似乎改了些规则,还有部分翻译不是很准确。比如虚拟文本的定义部分与原文有些出入,不知道TINYA有没有注意到。
最后,很感谢TINYA 对这个算法的介绍。
另外,有对这个算法感兴趣的朋友希望能大家一起讨论下
我的QQ:24888086
msn:[email protected]
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/tingya/archive/2006/02/18/601836.aspx
http://www.hackhome.com/InfoView/Article_119867.html
linux下用valgrind检查程序内存泄漏
问题提出:
如果一个较复杂的程序,有内存泄漏,如何检测?
在windows下,VC本身带有内存泄漏的检查,程序结束时输出窗口会提示有多少memory leaks. linux下有什么办法呢?
1.发现内存泄漏,可以用top或ps。
zhouhh@zhh64:~/smscore$ top | grep firefox
会持续打印firefox的内存占用状况,可以重定向到文件中。
2.静态检测
用splint, PC-LINT,IBM的 BEAM(IBM Checking Tool for Bugs Errors and Mistakes)等。在本文略过。
3.动态检测
有IBM的rational purify,开源的valgrind. 本文主要介绍valgrind。
Valgrind 现在提供多个工具,其中最重要的是 Memcheck,Cachegrind,Massif 和 Callgrind。Valgrind 是在 Linux 系统下开发应用程序时用于调试内存问题的工具。它尤其擅长发现内存管理的问题,它可以检查程序运行时的内存泄漏问题。其中的 memecheck 工具可以用来寻找 c、c++ 程序中内存管理的错误。可以检查出下列几种内存操作上的错误:
* 读写已经释放的内存
* 读写内存块越界(从前或者从后)
* 使用还未初始化的变量
* 将无意义的参数传递给系统调用
* 内存泄漏
valgrind网址:http://valgrind.org/。到现在为止最新版:3.60,支持ubuntu 10.10.对centos 5.2可以直接编译安装使用,ubuntu中遇到一些问题。
3.1下载
zhouhh@zhh64:~/valgrind$ wget http://valgrind.org/downloads/valgrind-3.6.0.tar.bz2
我开始用较老的版本,configure时遇到glibc版本太新的问题。
zhouhh@zhh64:~/valgrind/valgrind-3.4.1$ ./configure
…
checking the GLIBC_VERSION version… unsupported version
configure: error: Valgrind requires glibc version 2.2 – 2.10
我的系统环境:
zhouhh@zhh64:~$ uname -a
Linux zhh64 2.6.35-24-generic #42-Ubuntu SMP Thu Dec 2 02:41:37 UTC 2010 x86_64 GNU/Linux
zhouhh@zhh64:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=10.10
DISTRIB_CODENAME=maverick
DISTRIB_DESCRIPTION=”Ubuntu 10.10″
zhouhh@zhh64:~$ ls -l /lib/libc.so.6
lrwxrwxrwx 1 root root 14 2010-11-22 09:58 /lib/libc.so.6 -> libc-2.12.1.sozhouhh@zhh64:~$ ls /lib/libc*
/lib/libc-2.12.1.so
zhouhh@zhh64:~$ /lib/libc.so.6
GNU C Library (Ubuntu EGLIBC 2.12.1-0ubuntu10) stable release version 2.12.1, by Roland McGrath et al.zhouhh@zhh64:~$ gcc -v
Using built-in specs.
Target: x86_64-linux-gnu
gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)
下载完成后,解压tar xvf valgrind-3.6.0.tar.bz2,然后configure,编译安装,都没有问题。
zhouhh@zhh64:~/valgrind/valgrind-3.6.0$ ./configure
zhouhh@zhh64:~/valgrind/valgrind-3.6.0$ make
zhouhh@zhh64:~/valgrind/valgrind-3.6.0$ sudo make install
例1.使用未初始化的内存
代码如下
#include <stdio.h>
int main()
{
int x;
if(x == 0)
{
printf("X is zero");
}
return 0;
}
Valgrind提示如下
==14222== Conditional jump or move depends on uninitialised value(s)
==14222== at 0x400484: main (sample2.c:6)
X is zero==14222==
==14222== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 5 from 1)
==14222== malloc/free: in use at exit: 0 bytes in 0 blocks.
==14222== malloc/free: 0 allocs, 0 frees, 0 bytes allocated.
==14222== For counts of detected errors, rerun with: -v
==14222== All heap blocks were freed -- no leaks are possible.
例2.内存读写越界
代码如下
#include <stdlib.h>
#include <stdio.h>
int main(int argc,char *argv[])
{
int len=5;
int i;
int *pt=(int*)malloc(len*sizeof(int));
int *p=pt;
for(i=0;i<len;i++)
{p++;}
*p=5;
printf(“%d”,*p);
return;
}
Valgrind提示如下
==23045== Invalid write of size 4
==23045== at 0x40050A: main (sample2.c:11)
==23045== Address 0x4C2E044 is 0 bytes after a block of size 20 alloc'd
==23045== at 0x4A05809: malloc (vg_replace_malloc.c:149)
==23045== by 0x4004DF: main (sample2.c:7)
==23045==
==23045== Invalid read of size 4
==23045== at 0x400514: main (sample2.c:12)
==23045== Address 0x4C2E044 is 0 bytes after a block of size 20 alloc'd
==23045== at 0x4A05809: malloc (vg_replace_malloc.c:149)
==23045== by 0x4004DF: main (sample2.c:7)
5==23045==
==23045== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 5 from 1)
==23045== malloc/free: in use at exit: 20 bytes in 1 blocks.
==23045== malloc/free: 1 allocs, 0 frees, 20 bytes allocated.
==23045== For counts of detected errors, rerun with: -v
==23045== searching for pointers to 1 not-freed blocks.
==23045== checked 66,584 bytes.
==23045==
==23045== LEAK SUMMARY:
==23045== definitely lost: 20 bytes in 1 blocks.
==23045== possibly lost: 0 bytes in 0 blocks.
==23045== still reachable: 0 bytes in 0 blocks.
==23045== suppressed: 0 bytes in 0 blocks.
==23045== Use --leak-check=full to see details of leaked memory.
例3.src和dst内存覆盖
代码如下
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc,char *argv[])
{ char x[50];
int i;
for(i=0;i<50;i++)
{x[i]=i;}
strncpy(x+20,x,20); //Good
strncpy(x+20,x,21); //Overlap
x[39]=’\0’;
strcpy(x,x+20); //Good
x[39]=40;
x[40]=’\0’;
strcpy(x,x+20); //Overlap
return 0;
}
Valgrind提示如下
==24139== Source and destination overlap in strncpy(0x7FEFFFC09, 0x7FEFFFBF5, 21)
==24139== at 0x4A0724F: strncpy (mc_replace_strmem.c:116)
==24139== by 0x400527: main (sample3.c:10)
==24139==
==24139== Source and destination overlap in strcpy(0x7FEFFFBE0, 0x7FEFFFBF4)
==24139== at 0x4A06E47: strcpy (mc_replace_strmem.c:106)
==24139== by 0x400555: main (sample3.c:15)
==24139==
==24139== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 5 from 1)
==24139== malloc/free: in use at exit: 0 bytes in 0 blocks.
==24139== malloc/free: 0 allocs, 0 frees, 0 bytes allocated.
==24139== For counts of detected errors, rerun with: -v
==24139== All heap blocks were freed -- no leaks are possible.
例4.动态内存管理错误
常见的内存分配方式分三种:静态存储,栈上分配,堆上分配。全局变量属于静态存储,它们是在编译时就被分配了存储空间,函数内的局部变量属于栈上分配,而最灵活的内存使用方式当属堆上分配,也叫做内存动态分配了。常用的内存动态分配函数包括:malloc, alloc, realloc, new等,动态释放函数包括free, delete。
一旦成功申请了动态内存,我们就需要自己对其进行内存管理,而这又是最容易犯错误的。常见的内存动态管理错误包括:
l 申请和释放不一致
由于 C++ 兼容 C,而 C 与 C++ 的内存申请和释放函数是不同的,因此在 C++ 程序中,就有两套动态内存管理函数。一条不变的规则就是采用 C 方式申请的内存就用 C 方式释放;用 C++ 方式申请的内存,用 C++ 方式释放。也就是用 malloc/alloc/realloc 方式申请的内存,用 free 释放;用 new 方式申请的内存用 delete 释放。在上述程序中,用 malloc 方式申请了内存却用 delete 来释放,虽然这在很多情况下不会有问题,但这绝对是潜在的问题。
l 申请和释放不匹配
申请了多少内存,在使用完成后就要释放多少。如果没有释放,或者少释放了就是内存泄露;多释放了也会产生问题。上述程序中,指针p和pt指向的是同一块内存,却被先后释放两次。
l 释放后仍然读写
本质上说,系统会在堆上维护一个动态内存链表,如果被释放,就意味着该块内存可以继续被分配给其他部分,如果内存被释放后再访问,就可能覆盖其他部分的信息,这是一种严重的错误,上述程序第16行中就在释放后仍然写这块内存。
下面的一段程序,就包括了内存动态管理中常见的错误。
#include <stdlib.h>
#include <stdio.h>
int main(int argc,char *argv[])
{ char *p=(char*)malloc(10);
char *pt=p;
int i;
for(i=0;i<10;i++)
{p[i]=’z’;}
delete p;
p[1]=’a’;
free(pt);
return 0;
}
Valgrind提示如下
==25811== Mismatched free() / delete / delete []
==25811== at 0x4A05130: operator delete(void*) (vg_replace_malloc.c:244)
==25811== by 0x400654: main (sample4.c:9)
==25811== Address 0x4C2F030 is 0 bytes inside a block of size 10 alloc'd
==25811== at 0x4A05809: malloc (vg_replace_malloc.c:149)
==25811== by 0x400620: main (sample4.c:4)
==25811==
==25811== Invalid write of size 1
==25811== at 0x40065D: main (sample4.c:10)
==25811== Address 0x4C2F031 is 1 bytes inside a block of size 10 free'd
==25811== at 0x4A05130: operator delete(void*) (vg_replace_malloc.c:244)
==25811== by 0x400654: main (sample4.c:9)
==25811==
==25811== Invalid free() / delete / delete[]
==25811== at 0x4A0541E: free (vg_replace_malloc.c:233)
==25811== by 0x400668: main (sample4.c:11)
==25811== Address 0x4C2F030 is 0 bytes inside a block of size 10 free'd
==25811== at 0x4A05130: operator delete(void*) (vg_replace_malloc.c:244)
==25811== by 0x400654: main (sample4.c:9)
==25811==
==25811== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 5 from 1)
==25811== malloc/free: in use at exit: 0 bytes in 0 blocks.
==25811== malloc/free: 1 allocs, 2 frees, 10 bytes allocated.
==25811== For counts of detected errors, rerun with: -v
==25811== All heap blocks were freed -- no leaks are possible.
例5.内存泄漏
代码如下
#include <stdlib.h>
int main()
{
char *x = (char*)malloc(20);
char *y = (char*)malloc(20);
x=y;
free(x);
free(y);
return 0;
}
Valgrind提示如下
==19013== Invalid free() / delete / delete[]
==19013== at 0x4A0541E: free (vg_replace_malloc.c:233)
==19013== by 0x4004F5: main (sample5.c:8)
==19013== Address 0x4C2E078 is 0 bytes inside a block of size 20 free'd
==19013== at 0x4A0541E: free (vg_replace_malloc.c:233)
==19013== by 0x4004EC: main (sample5.c:7)
==19013==
==19013== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 5 from 1)
==19013== malloc/free: in use at exit: 20 bytes in 1 blocks.
==19013== malloc/free: 2 allocs, 2 frees, 40 bytes allocated.
==19013== For counts of detected errors, rerun with: -v
==19013== searching for pointers to 1 not-freed blocks.
==19013== checked 66,584 bytes.
==19013==
==19013== LEAK SUMMARY:
==19013== definitely lost: 20 bytes in 1 blocks.
==19013== possibly lost: 0 bytes in 0 blocks.
==19013== still reachable: 0 bytes in 0 blocks.
==19013== suppressed: 0 bytes in 0 blocks.
==19013== Use --leak-check=full to see details of leaked memory.
例6.非法写/读
代码如下
int main()
{
int i, *x;
x = (int *)malloc(10*sizeof(int));
for (i=0; i<11; i++)
x[i] = i;
free(x);
}
Valgrind提示如下
==21483== Invalid write of size 4
==21483== at 0x4004EA: main (sample6.c:6)
==21483== Address 0x4C2E058 is 0 bytes after a block of size 40 alloc'd
==21483== at 0x4A05809: malloc (vg_replace_malloc.c:149)
==21483== by 0x4004C9: main (sample6.c:4)
==21483==
==21483== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 5 from 1)
==21483== malloc/free: in use at exit: 0 bytes in 0 blocks.
==21483== malloc/free: 1 allocs, 1 frees, 40 bytes allocated.
==21483== For counts of detected errors, rerun with: -v
==21483== All heap blocks were freed -- no leaks are possible.
例7.无效指针
代码如下
#include <stdlib.h>
int main()
{
char *x = malloc(10);
x[10] = 'a';
free(x);
return 0;
}
Valgrind提示如下
==15262== Invalid write of size 1
==15262== at 0x4004D6: main (sample7.c:5)
==15262== Address 0x4C2E03A is 0 bytes after a block of size 10 alloc'd
==15262== at 0x4A05809: malloc (vg_replace_malloc.c:149)
==15262== by 0x4004C9: main (sample7.c:4)
==15262==
==15262== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 5 from 1)
==15262== malloc/free: in use at exit: 0 bytes in 0 blocks.
==15262== malloc/free: 1 allocs, 1 frees, 10 bytes allocated.
==15262== For counts of detected errors, rerun with: -v
==15262== All heap blocks were freed -- no leaks are possible.
例8.重复释放
代码如下
#include <stdlib.h>
int main()
{
char *x = malloc(10);
free(x);
free(x);
return 0;
}
Valgrind提示如下
==15005== Invalid free() / delete / delete[]
==15005== at 0x4A0541E: free (vg_replace_malloc.c:233)
==15005== by 0x4004DF: main (sample8.c:6)
==15005== Address 0x4C2E030 is 0 bytes inside a block of size 10 free'd
==15005== at 0x4A0541E: free (vg_replace_malloc.c:233)
==15005== by 0x4004D6: main (sample8.c:5)
==15005==
==15005== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 5 from 1)
==15005== malloc/free: in use at exit: 0 bytes in 0 blocks.
==15005== malloc/free: 1 allocs, 2 frees, 10 bytes allocated.
==15005== For counts of detected errors, rerun with: -v
==15005== All heap blocks were freed -- no leaks are possible.
Valgrind的局限
l Valgrind不对静态数组(分配在栈上)进行边界检查。如果在程序中声明了一个数组:
int main()
{
char x[10];
x[11] = 'a';
}
Valgrind则不会警告你,你可以把数组改为动态在堆上分配的数组,这样就可能进行边界检查了。这个方法好像有点得不偿失的感觉。
l Valgrind占用了更多的内存--可达两倍于你程序的正常使用量。如果你用Valgrind来检测使用大量内存的程序就会遇到问题,它可能会用很长的时间来运行测试。大多数情况下,这都不是问题,即使速度慢也仅是检测时速度慢,如果你用Valgrind来检测一个正常运行时速度就很慢的程序,这下问题就大了。 Valgrind不可能检测出你在程序中犯下的所有错误--如果你不检查缓冲区溢出,Valgrind也不会告诉你代码写了它不应该写的内存。
参考文章:
http://www.cnblogs.com/xuybin/p/3166904.html
http://blog.csdn.net/wzzfeitian/article/details/8567030
http://www.ibm.com/developerworks/cn/linux/l-cn-valgrind/
http://www.oschina.net/translate/valgrind-memcheck
Fix Memory Leaks in Java Production Applications - Dynatrace APM Blog
诊断识别解决 Java 内存泄漏
Adding more memory to your JVMs (Java Virtual Machines) might be a temporary solution to fixing memory leaks in Java applications, but it for sure won’t fix the root cause of the issue. Instead of crashing once per day it may just crash every other day. “Preventive” restarts are also just another desperate measure to minimize downtime – but – let’s be frank: this is not how production issues should be solved.
One of our customers – a large online retail store – ran into such an issue. They run one of their online gift card self-service interfaces on two JVMs. Especially during peak holiday seasons – when users are activating their gift cards or checking the balance – crashes due to OOM (Out Of Memory) were more frequent which caused bad user experience. The first “measure” they took was to double the JVM Heap Size. This didn’t solve the problem as JVMs were still crashing, so they followed the memory diagnostics approach for production as explained in Java Memory Leaks to identify and fix the root cause of the problem.
Before we walk through the individual steps, let’s look at the memory graph that shows the problems they had in December during the peak of the holiday season. The problem persisted even after increasing the memory. They could fix the problem after identifying the real root cause and applying specific configuration changes to a 3rd party software component:
After identifying the actual root cause and applying necessary configuration changes did the memory leak issue go away? Increasing Memory was not even a temporary solution that worked.
Step 1: Identify a Java Memory Leak
The first step is to monitor the JVM/CLR Memory Metrics such as Heap Space. This will tell us whether there is a potential memory leak. In this case we see memory usage constantly growing resulting in an eventual runtime crash when the memory limit is reached.
Java Heap Size of both JVMs showed significant growth starting Dec 2nd and Dec 4th resulting in a crash on Dec 6th for both JVMs when the 512MB Max Heap Size was exceeded.
Step 2: Identify problematic Java Objects
The out-of-memory exception automatically triggers a full memory dump that allows for analysis of which objects consumed the heap and are most likely to be the root cause of the out-of-memory crash. Looking at the objects that consumed most of the heap below indicates that they are related to a 3rd party logging API used by the application.
Sorting by GC (Garbage Collection) Size and focusing on custom classes (instead of system classes) shows that 80% of the heap is consumed by classes of a 3rd party logging framework
A closer look at an instance of the VPReportEntry4 shows that it contains 5 Strings – with one consuming 23KB (as compared to several bytes of other string objects).This also explains the high GC Size of the String class in the overall Heap Dump.
Following the referrer chain further up reveals the complete picture. The EventQueue keeps LogEvents in an Array which itself keeps VPReportEntrys in an Array. All of these objects seem to be kept in memory as the objects are being added to these arrays but never removed and therefore not garbage collected:
Following the referrer tree reveals that global EventQueue objects hold on to the LogEvent and VPReportEntry objects in array lists which are never removed from these arrays
Step 3: Who allocates these objects?
Analyzing object allocation allows us to figure out which part of the code is creating these objects and adding them to the queue. Creating what is called a “Selective Memory Dump” when the application reached 75% Heap Utilization showed the customer that the ReportWriter.report method allocated these entries and that they have been “living” on the heap for quite a while.
It is the report method that allocates the VPReportEntry objects which stay on the heap for quite a while
Step 4: Why are these objects not removed from the Heap?
The premise of the 3rd party logging framework is that log entries will be created by the application and written in batches at certain times by sending these log entries to a remote logging service using JMS. The memory behavior indicates that – even though these log entries might be sent to the service, these objects are not always removed from the EventQueue leading to the out-of-memory exception.
Further analysis revealed that the background batch writer thread calls a logBatch method which loops through the event queue (calling EventQueue.next) to send current log events in the queue. The question is whether as many messages were taken out of the queue (using next) vs put into the queue (using add) and whether the batch job is really called frequently enough to keep up with the incoming event entries. The following chart shows the method executions of add, as well as the call to logBatch highlighting that logBatch is actually not called frequently enough and therefore not calling next to remove messages from the queue:
The highlighted area shows that messages are put into the queue but not taken out because the background batch job is not executed. Once this leads to an OOM and the system restarts it goes back to normal operation but older log messages will be lost.
Step 5: Fixing the Java Memory Leak problem
After providing this information to the 3rd party provider and discussing with them the number of log entries and their system environment the conclusion was that our customer used a special logging mode that was not supposed to be used in high-load production environments. It is like running with DEBUG log level in a high load or production environment. This overwhelmed the remote logging service and this is why the batch logging thread was stopped and log events remained in the EventQueue until the out of memory occurred.
After making the recommended changes the system could again run with the previous heap memory size without experiencing any out-of-memory exceptions.
The Memory Leak issue has been solved and the application now runs even with the initial 512MB Heap Space without any problem.
They still use the same dashboards they have built to troubleshoot this issue, to monitor for any future excessive logging problems.
These dashboards allow them to verify that the logging framework can keep up with log messages after they applied the changes.
Conclusion
Adding additional memory to crashing JVMs is most often not a temporary fix. If you have a real Java memory leak it will just take longer until the Java runtime crashes. It will even incur more overhead due to garbage collection when using larger heaps. The real answer to this is to use the simple approach explained here. Look at the memory metrics to identify whether you have a leak or not. Then identify which objects are causing the issue and why they are not collected by the GC. Working with engineers or 3rd party providers (as in this case) will help you find a permanent solution that allows you to run the system without impacting end users and without additional resource requirements.
Next Steps
If you want to learn more about Java Memory Management or general Application Performance Best Practices check out our free online Java Enterprise Performance Book. Existing customers of our APM Solution may also want to check out additional best practices on our APM Community.
YYeTs人人影视正在清理内容
KPT:http://kickass.so/
addic7ed:: http://www.addic7ed.com/
yayaxz:http://www.torrentreactor.net/
eztv:http://eztv.it/
Universe:http://yzys.tv/
Rarbg:http://www.rarbg.com/
opensubtitles:http://www.opensubtitles.org
seriessub:http://www.seriessub.com/
bitmetv:http://www.bitmetv.org/
extratorrent:http://extratorrent.cc/
yts:http://yts.re/
monovahttp://www.monova.org/
torrentreactor:http://www.torrentreactor.net/
movie4k:http://www.movie4k.to/
KPT:http://kickass.so/
射手字幕站: http://shooter.cn/
丫丫下载站:http://www.torrentreactor.net/
美剧片源下载:http://eztv.it/
Rarbg片源站:http://www.rarbg.com/
全球字幕站:http://www.opensubtitles.org
法国美剧字幕站:http://www.seriessub.com/
最强美剧PT站:http://www.bitmetv.org/
宇宙影视站:http://yzys.tv/
天天美剧:http://www.ttmeiju.com/
伊甸园字幕组:http://bbs.sfile2012.com
破烂熊字幕组:http://www.ragbear.com/
风软字幕组:http://www.1000fr.net/
http://www.disanlou.org/
http://www.subom.net/
http://subhd.com/
http://sub.makedie.me/
ODBC、OLE DB、ADO 数据访问 - 维基百科,自由的百科全书
ODBC
ODBC (Open Database Connectivity) 是由 SQL Access Group,X/Open (目前为 The Open Group 的一部份) 以及 ISO/EIC 所提出的 Call Level Interface (CLI) (调用层次接口) 接口规格[1],由微软开发出第一份 ODBC 的实作,每一个数据库都可以实作出链接自家数据源的 ODBC 驱动程序 (Driver),而应用程序开发人员能够利用 ODBC 所开放的 API 调用,经由 ODBC Driver 来进入数据库进行访问以及处理工作。
ODBC 现在已经是大多数平台上的共同数据访问标准,并且后续由各软件厂商提出的数据访问规格,多数都和 ODBC 有类似的规格。
由Microsoft提出的类似 ODBC 的数据库访问规格,但它是使用 COM 以及 Provider-Based 模型来建构,OLE DB 规格[3]中定义了许多的接口,由数据库提供者 (database provider) 来实作这些接口,应用程序开发人员则直接利用 COM 调用这些 OLE DB 接口来连接与访问数据。但 Microsoft 也实作了可以桥接 ODBC Driver 的提供者:OLE DB Provider for ODBC,在微软 Windows 应用平台中被大量使用于数据访问中。与 JDBC 不同的是 JDBC 是属于 Java 编程语言的专属规格,但 OLE DB 可以被能够调用 COM 接口的任何编程语言使用。
OLE DB 也是 ADO 以及 ADO.NET 的核心基础,而这些 API 目前也被广为用在微软 Windows 应用平台中。
高考挤入全省前1%,对今后的生活会有哪些帮助? - 苏菲的回答 - 知乎
同学你好,我在当年的高考中有幸挤入全省0.01%,自那以后已经过了八年,虽然我还年轻,看到的事情并不是很多,但是希望我自己的一点感悟能对你有所帮助。
我觉得虽然题目说,“高考挤进1%对今后的生活有哪些帮助?" 但是你想知道的其实是“高考挤进全省1%,意味着什么?该怎么做?”于是想从这个角度来答问题。
1,正确认识自己的成绩代表的意义
首先让我们大家沉思少许,这个1%,也就是相对于其他人较优秀的学习成绩,到底意味着什么?
我想你可能已经认识到这个问题了。因为你说过“但我对学习成绩和今后生活之间的关系有些迷惑”。没错,在我们小时候那个时代,几乎就是学习成绩代表一切。学习好,老师也喜欢,家长也夸奖,甚至同班同学有不良少年都不敢欺负你。但是随着我们逐渐接触社会,却会发现当年的那个“挡箭牌”愈发的不好使了。那是因为小时候的价值观根本就是片面的。
成绩代表了:一定的理解能力(对于课本上讲述的知识),一定的举一反三运用能力(可以运用知识解出没做过的题),一定的毅力和努力,一定的记忆力。
你有可能具备但是不一定具备的:好的学习方法以及发现方法的能力;理解条理,逻辑和语言能力;比较好的心理素质(以保证考试的时候能很好地发挥);大脑运转的速度(以保证在考试限制时间内解出题目)。
如果你的成绩算是佼佼者,那么祝贺你,至少你以上的一部分能力是比大部分人都优秀的。成绩好,毫无疑问是一个肯定。但是我们要清楚它肯定的是什么,令我们成绩好的到底是什么样的素质,在今后可以有什么样的利用。
请允许我拿自己做个例子。其实进了大学之后在自己专业学习方面,因为没有太过硬的抗击失败的心理素质导致受到不适宜的教育方法后很快失去了兴趣。当时在我的情况下申请去美国留学非常难,因为要设计做的很有想法很精彩才有可能的。但是正好我想申请的日本,比起美国更看重语言成绩和大学。通过高中的学习我清楚自己学习语言还是有一些心得的,于是就靠比较好的语言成绩申请上了东京大学。回避了我的设计作品这个弱点。
带给你的第一个帮助:有一个客观的衡量标准,能让你知道自己的确在哪些方面擅长,也让你知道自己的弱项。这在今后的日子里可以让你更好的取长避短。
2,正确认识自己和他人的关系。
毫不避讳地说,当年高考完毕竟是年轻,因为放低志愿进了非清北的学校,导致大学时代前期我对自己和他人的水平认识有一定的偏差的。——当时的我太倚重自己的小聪明了。殊不知,每一行当每一件事需要的天分不同,过去的好成绩不一定代表了将来的成功。对于自己成绩的飘飘然也导致我对于在大学的专业课里得不到承认的心理落差,最终轻易放弃。
回想大学时代,很多朋友对我都很好,我却因为这种pride没能与他们真正交心。错过学业并不可怕,错过真正的朋友才是终生之憾。
而留学之后,较多的接触了其他一些并不是录取分数线很高的学校的学生,也接触了一些其他的清华北大生,让人感触良多。优秀的大学也许优秀的学生比较多,但是不那么优秀的大学也永远会有让你敬佩比你厉害的人存在着。不要因为虚荣的名声局限了自己,看低了他人。
带给你的第二个帮助:让你进入一个相对较好的学校环境,能认识很多优秀的人,这是非常重要的影响和激励。
可以参考相关答案:http://www.zhihu.com/question/20148791/answer/15191880
第二个警示:任何人都有强项和弱项,要看到他人比自己强的地方,保持虚心才能继续进步。与人交往,忘记自己的一切。
3,正确认识到将来的不确定性。
也许有的朋友看到我说自己是省内0.01%,要觉得有些炫耀的成分在。但其实我这个成绩在当时的班级里并不算什么。那个班出了二三十的清华北大,而我只是普通的的一员而已。你切莫觉得这也是炫耀,慢慢听我道来。
正是当年这些优秀的同窗们,让我认识到将来的不确定性。
你提到“努力取得一个相对较好的成绩,能够保证我将来有一个较好的生活吗?”,那就让我讲讲我看到的这些朋友他们的路。
清华北大就一定顺利吗?当然不。他们之中有非常优秀的人,毕业工作了以后,不顺心又只好考研,或者读博士读的艰难困苦。包括我自己大学后期准备申请日本的时候也是很艰难的一段日子。高考考得好必然不等于之后的一帆风顺,甚至还有可能因为进入了太优秀的环境而找不到自己的定位,郁郁寡欢。
而唯一能保证将来的确定性的,就是持续的谦虚与努力。
仅仅努力在高考中取得一个相对好的成绩,是远远不够的。高考考好了就一马平川了,在现在的社会中不存在。但是如果你每一步都去努力取的好成绩,这些成绩就会慢慢积累,就真的会让你的生活越来越好。
我那些值得敬佩的同窗们也是这样的。他们当中也不乏复读的人,也不乏去了普通学校然后一步一步继续努力又回到了顶级学校的人。
带给你的第三个帮助:让你确信努力带来的价值。为你今后不断努力的人生铺好第一个台阶。
第三个警示:努力是没有尽头的,一劳永逸不存在。
资历尚浅,仅谈谈个人感受。有幼稚之处,希望阅历更丰富的前辈指正。
最后希望题主能努力在高考中取得好成绩。纵然它不代表一切,但是对于一个高三学生来说,它绝对是你踏入优秀群体,为将来打下坚实基础的最快捷也最靠谱的方法。
怎样在两百天里科学高效地提高高考成绩? - 苏菲的回答 - 知乎
高三是在我目前为止平凡的人生中唯一一段特别的经历。非常想和大家分享。
背景是这样的:高一高二我特别贪玩,混到高三在班级里大概四五十多名,教材上的化学方程式都背不出。某次化学老师让我上黑板,非常基础的方程,结果几个人只有我被挂上面。老师鄙夷的看了我一眼,然后让我同桌一个踏实又努力的女孩子上去顺利写了出来。
我虽然非常喜欢我同桌和化学老师,却怎么也忘不了当时老师的眼神和那种耻辱...
然后就突然发誓说要考清华,一定要上。
以前的我是个有点不待见努力吭哧吭哧做题这样行径的爱耍小聪明的孩纸。因为知道自己缺乏长时间集中力这个缺点,所以从最开始到最后都是以高效率为原则的。
第一件事,把教材吃透。
前提是认真跟着各科老师高三的总复习。总复习是一个重新跟上的最好的机会,错过了就很难再有时间追基础知识了,尽量不要抛下学校的学业去独立复习。然后自习时间和课余时间额外给自己开小灶。这里的关键点有两个:
1,让教材滚瓜烂熟。
我在高三找到的一个看书的学习方法是回想法。对于需要我背诵或者特别熟练的内容,光看是没用的,记不住。我会在每看完一段之后合上书,自己把这一段写下来,或者用自己的话说出来,或者自己把这一段的知识结构整理写出来。当你能产出的时候,才是真正理解的时候。就这样一点点把所有教材全扫一遍。
当时即使是看教材不那么重要的科目,我都会发现很多老师甚至没强调的细节,非常有收获。
2,要选择一本非常非常好的参考书。
大家都在用的不一定就是好的。一定要去书店,挨个一本本看。什么样的参考书是好的呢?讲基础知识多,有所扩展,并且有很多原创的知识整理,能把教材里的整个知识网络清晰地展示给你看。题目不一定要多(题目可以买专门做题的书),甚至都不一定要做。
同时这本书一定要看起来很容易,有的书会讲的很晦涩或者选题很偏。多翻翻,甚至找一个你一直弄不明白的知识点,看看那本书你站在那里读5分钟后会有一种恍然大悟的感觉,就对了。
然后,随着老师的总复习脚步,同步去把这本书以及教材搞透。
这件事情,要用几个月去做。高三老师天天发卷子留作业,自己可以控制的时间其实非常有限,要充分利用,不用着急去一本本做题(这期间跟着老师也能做不少题了),即使是你身边的大牛已经开始查缺补漏了——有一天你会超过他的。
如果能完成,那么这时候你的成绩一定已经比之前提高了很多了。
第二件事,把题型吃透。
就是把吃透的知识转化为实战的能力。
高考虽然有灵活的一面,但是跑不出基本的出题思路——因为它总是要以教材为基础,去考察教材的某个部分的。这时候我们要选择的参考书,就是能智慧地收集并且总结主要题型的书。
很多书里面一堆题,然后分类很乱。记住,要突飞猛进,我们就要比他人完成更多的事情,因此时间更有限,题海战术最要不得。如果不找到高效率的方法,就是死路一条。
一本最理想的题目书,会把某个知识点下面可以出的不同类型的题给你看,然后每个类型的题练个两三次,加上讲解。市面上不一定有这种100%理想的书。没关系,买一本最相近的,别忘了老师也会发材料,你还可以自己总结。总复习到每个知识点的时候,老师都会集中的发该知识点的题目,这是一个好机会。把常出的题型记住,就像教材那样熟悉他们。
关于错题本,当时其实我也弄了一个。但除了第一次写上的时候帮助记忆以外,基本没翻过……我认为更有用的是总结题型并且记到自己脑袋里。
吃透题型后,每看到一个题目,我们都能在心里大概浮现出这个题目考的是什么知识点,应该从哪里入手作答。实话说,如果能做到这一点,那基本你考试就能所向披靡了!
第三件事,抓住上战场的宝贵机会。
战场,即是模考。到复习后期,基本上每一个月都会有一次大型的,正式的模拟考试。基本模拟高考。老师还会把每次考试的成绩打出来供比较分析用。
这就到了我们刷荣誉的时候了!!!!
这个宝贵的机会,可以让我们实现两件事:
1,验证自己的能力,知道自己处在什么位置。
考试是一个特别特别好的实验场所。你可以知道自己的复习达到了一个什么效果。我希望你在这时看到的是不断上升的排名,这说明你的努力非常有成效。但是如果不是,也不要着急。我当时是奇特的以好一次坏一次的节奏,总体上升,最后几次才保持了连续上升的趋势。
2,检测自己的不足,进行改进。
如果模考不尽理想,那也是个好事。因为你可以看到很多自己不足的地方。模考其实还是个试验场,你可以尝试不同的考试的策略,做题方法(比如作文的不同写法,英语阅读的不同读法等),并且找到那个最适合你的。
当时我有那么一本日记,除了写写日常心情鼓励鼓励自己之外,还会对每一次模考彻底分析。包括记录下每科分数,然后逐科分析这一次发挥好在哪里,弱点在哪里,什么地方该拿分却丢分了,什么地方是本身掌握的就不够,什么地方是题目出的太偏不要在意。写出来,是一个理性整理的过程,也是让自己客观看待考试结果的过程。还可以之后翻看。
另外在这样的日记的最后我还会决定一下之后的复习该干什么,下次考试该尝试什么样的的方法等,之后的行动就明确了。
我就是通过这三件事成为“黑马”的。
还有一些其他的:
关于紧张
考试紧张大抵是因为,没有信心,导致,害怕失败。
信心的有无跟准备充分与否有关,但是害不害怕失败我们自己可以控制。我们是希望模考每次都发挥超常导致自己不知道自己的弱项导致高考不靠谱呢?还是希望模考可以充分暴露出自己的缺点让我们可以去把它们各个击破?
关于励志
即使我走的是追求效率而非题海战术,也不得不说,这个过程的确非常枯燥。
曾经好多次在漫漫晚自习里抬起头来,长叹口气。学习这件事必然是没有玩游戏乐趣大的。所以一个目标,精神上的鼓励非常非常重要,否则很难坚持。
以前回校的时候曾经和学弟学妹说过,你现在的排名,除以十,能考上的学校,就是你的目标。据说当时搞得大家都雀跃的人人去除以十……
我觉得这个没错。但最关键的在于你要去给自己洗脑让自己相信真的非这里不去。光嘴上说说我要去xxx学校而心里没底,是没用的。就要破釜沉舟,对自己狠一把。
另外,在那段时间也不是完全没有娱乐活动的。高三比较喜欢看《火影忍者》和《钢铁是怎样炼成的》,哦不,是《钢之炼金术师》。当时看着鸣人那个小吊车尾是怎么一遍遍说着自己要当火影,遍体鳞伤也慢慢坚持的故事,给我很大的鼓励。艾德所说的等价交换的道理,也让我当时深深相信努力就一定会有回报。(至少在高考这件事上,努力和回报是基本成正比的)
时不时还听听周杰伦“瓜牛”,i believe i can fly这类励志小歌曲。
保持一个打鸡血的状态是非常重要的……
关于学习时间
我非常不提倡长时间连续学习以及熬夜学习这种拼法。消耗掉体力什么的倒还好说,但是精神上的消耗是非常大的。不利于保持高效率。
课间就痛快的玩,和同班同学插科打诨,大声闹大声笑,把压力都释放出来。该学习的时候才学。
上大学之前我从来没有晚上超过10点睡觉。熬夜没什么意义,只是拿放弃第二天的代价来补这一点的罪恶感罢了。要保持头脑清醒。
该放松就放松,没事跟同学出去玩玩。
其他
成绩发生明显提高是在高考当年1-4月份这段时间。也有可能因为考试多所以能看出来成绩的进步。最后的结果请参见如果高考能挤入全省前1%,对今后的生活会有哪些帮助?
不过最后我没报清华,这也是很重要的,
目标是一回事,到了报考要考虑很多东西。但那都是在你有一个可以给自己足够自由的分数为前提的。所以那之前不用想太多,朝着光环努力即可。人生又有几次全心全意义无反顾的瞬间呢。
另外每个人情况和环境不同,所以仅供参考。找到自己最适合的方法才最重要。
看到有的朋友说想试试这个答案的方法,在感到非常荣幸和感谢的同时也有一丝担心。怕这些同学对这个答案太过相信而耽误了自己。
这有点矛盾,既然是我提倡的学习方式,又怎么担心会耽误别人呢?
因为100%适合所有人的学习方式,是不存在的。我只是提出一些可能性而已,至于到底适不适合你,只有唯一的方法——实践。像这个问题下其他答案中不是也有熬夜学习效率特别高的同学吗?这世界上没有绝对的对,只有适合你的唯一。
因此,最重要的是:
始终保持一个清醒的头脑和愿意不断检讨现状,追寻改进方法的心态。
祝高三的学子们一切顺利。
你在高三是怎样大幅度提高成绩的? - Yihan Sun 的回答 - 知乎
我高三下学期之前一直以为自己要保送,加上高中的学习确实很枯燥,反正浪了两年半,以出去玩啦搞竞赛啦还有参加各种奇怪的活动为借口,文化课真的是相当荒废。然后高三寒假去考清华的保送考试,莫名其妙地就挂了(但是给了10分的自主招生降分,不过这不重要)。知道结果的那天我默默地把寒假作业都翻了出来(虽然最后也没写)……反正超级凄凉。开学的时候离高考还有108天。
由于自己非常作死,那时候铁了心非清华不去,我当时没有考其它任何学校的保送考试,总之就是要高考了。然后,开学后的第一个月我都在慢慢消化并接受自己要考高考的残酷事实。T_T
开学第二个月的模考我就直接考了学校的六十多名,这分肯定是上不了清华的,我们学校不要说六十名了,考第六都上不了清华。
我基础不弱,但是那时候落下了很多课程,应试能力也直降为0。人家高三第一轮复习的时候我都不知道在干嘛,人家刷完的题所有人都烂熟的那些我看着还觉得很新鲜T_T。
开学第三个月,也就是离考试还有个十天八天的时候,最后一次模考,没有全校排名(照顾大家的心态),我自己在心里算了一下自己的分数和可能的排名(毕竟有重点班,大家的分数互相也都是知道的),觉得自己准备好了,可以去高考了。
先说一下结果吧,今晚肯定写不完了,先挖个坑,有空来继续写。我最后考试是我们市第一名,省第四(其实有很多并列,都是这个分),如愿以偿地上了清华,选了自己最喜欢的专业。我觉得高三最后的这三个月,我的利用率还是挺高的。而且从小到大的大考,我基本上没怎么失过手(中考是全市第一,高考还是,不过变成并列的了~),所以对应试很有心得。我觉得应试能力强这不是什么耻辱的事情,再说我又不是别的能力不行只会考试,凡事都要动脑,既然注定要参加考试了,当然要找到合适的技巧最大发挥自己的能力咯~
我是江苏考生,当年还只考语数外三门,所以我尽我所能给你说说这三门吧。我尽量不说套话,说一些比较具体的且自己感觉有受益的部分,参考书里的什么“夯实基础”就不提啦~所以这里是不完全的建议哟!
语文
因为我是一个纯粹的理科女,所以我对语文答题是直接在脑子里训练模型的=。= @Yong He 说我语文好,真是惭愧。从纯粹的应试角度来说,我觉得语文考试答题是很需要技巧的,我觉得我抓住了技巧,所以语文成绩一直很高。从几个比较大的方面来说:
阅读,“XXX的描写有什么好处?”我只要在脑子里搜索一遍以前所有“描写 好处”的题目,大概不同的参考答案,写个七八条没问题,比如:1 营造气氛,2 呼应上文,3 铺垫下文,4 衬托主人公心情,5 与XX形成强烈的对比,等等等等,这种东西,日常找个小本子记下来,考试的时候看到这种题,把七八种可能性一列,往原文里一套,对得上就留下,对不上就丢掉,通常能写个四五条,一般语文考试都是踩点得分,把这些现成的东西往里一套,通常80%的分就到手了。再比如“XX一句用了什么的手法?请赏析”无非有:修辞(比喻,拟人,排比,等等),或者是比如直抒胸臆,借景抒情,寓情于景,或者是,白描,工笔,等等,这是可枚举的!然后下面就是:生动形象,富于动感,情景结合,营造了XXX的氛围,烘托了XXX的气氛,表达了XXX的感情,等等等。你看我都phd一年级了这种话还是连贯地往外蹦,简直是受毒害太深T_T
上面我所说的都是不完全的,如何有完整的训练集呢?去买一本高考复习的语文参考书,里面通常都有一些总结,自己总结整理一下,但是这也是不完全的。我比较提倡在自己做模拟卷的时候,写完阅读题对照答案,给自己踩点评个分,得多少分是次要的,主要是看看自己漏了哪一点。这一点有没有被自己总结过,总结过是自己背漏了还是写出来又被排除了,如果没总结过就加入总结的集合,这个集合就慢慢被完善。每次模考之前都背一遍,默写一遍。平常做题的时候也要用同样的思维方式,这样考试的时候才能手到擒来。
作文,这个太难说了,虽说套作不好,但是考场作文毕竟时间太短,我还是建议套作……又是那句话,从纯粹应试的角度来说,建议有如下几点:
1 知道自己的风格是什么。大多数人的高考作文会写议论文,因为非常保险。我自己因为从来都写散文,有几次模考改变了自己的风格,根本把握不住阅卷老师的心态(其实就是训练数据不足。。)所以就跪了。所以我个人建议考场作文的大风格大方向上考场之前就要有数,所有模考都按那一种风格写就行了,反正都是为高考服务。
2 既然模考作文风格都要一致了,准备一个摘抄本,比如写议论文,通常写议论文的人都是不管议论什么都用那几个事例的,呵呵呵呵呵,不要以为我不知道~所以!一个是读往年的优秀作文,摘抄他们用的好句子好例子,为我所用,看好在哪里,写个仿句,然后下次自己用。再一个是对自己写出来的作文反复修改,字斟句酌,完善论据,下一次考试再用一次~这样在考场上写出来的作文就不是那几十分钟匆忙写出来的,而是你打磨了一学期的呢~而且也不可能是抄袭,因为是你自己写的呀。
3 大家都知道高考阅卷速度巨快,作文这种东西不会细看。所以什么最重要?当然是开头和结尾!我建议,开头和结尾首先要切题,其次要华丽(修辞和生僻字是两个比较好的手段,但是千万不要过火,一定要有驾驭语言的能力,不要生硬地秀文采,因人而异,能驾驭到什么级别的语言,就用到极致,驾驭不了的,不要贻笑大方),最佳是首尾呼应。首尾呼应一定要有显式的照应,让人一眼就能看出。想象阅卷老师看了开头,匆匆扫过中间,再看结尾,看到了首尾呼应的部分,一定会认为你的文章结构完整,有条有理,那就是佳作。这一招我 一直觉得是我拿作文高分的一个关键。
4 当然,如果能做到的话,字美一点总是有好处的呀!
以上只是从一个学生的角度说通常情况下的应试经验~我自己觉得非常好使,当然对这些东西不能过于依赖,要具体情况具体分析。作文最重要的还是要切题,光套好文章不切题,都是白搭。
当然 @Yong He 说得对,语文本质上还是靠积累,高三还想在这方面有进步的话,可以利用休息的时间阅读做摘抄,用轻松一点的心态,读一些高质量的散文,议论文,或者文学评论/鉴赏(读高质量的文学评论,是读一送一的效果,即相当于温习了原作品,又学习了评论者的语言和理解,尤其是古文,诗词之类的东西,中间蕴含的深意太多,有时一知半解的,看看评论/鉴赏,不是那种古诗三百首底下给的浮于表面的赏析。当然啦,这种东西,真的感兴趣的肯定是要批判地接受,代入自己的思考的~)。我本人很喜欢看书,所以觉得休息时间干这个还是挺劳逸结合又有帮助的~
数学
题主妹妹看了你的成绩我特别想说:为什么不去学文科呢?
当然说这些已经晚了,不过看来数学才是题主最需要恶补的部分啊。
数学成绩不理想有很多很多种,不知道题主是哪一种。我们假设满分是x分,一个人会做的所有题目满打满算有y分,实际上只考出了z分。那么成绩不理想有三种情况,一种是(y/x)太低,一种是(z/y)太低,第三种是两种都低。我本人在相当长一段时间内一直是后一种,所以具体说说后一种,前一种呢,我也尽我所能提一些建议。
1 (z/y)指标低。我再分两种情况:
(1) 会做的题做!不!对!
比如,计算出错,或者是送分的小题出一些莫名其妙的错,之类的。我高三下刚开始进入高考复习状态的时候,填空题正确率简直是历史新低。这有一个传统的说法叫做“做题没有手感”。
相信很多人都听说过一个全国各地都有的逆天的存在,叫做“错题本”。但是错题本到底怎么用呢?正确的用法是:错题和答案分开写,然后把错题再!做!一!次!然后对照答案给自己批改。这就要求错题本上的题目质量要高,或者说这不再是一本“错题本”而是“精品集”。如果我做到了一道题,感觉非常适合再一次用来练习(比如用了绝佳的思路,或者需要极其繁琐的运算,很适合拿来练计算能力),即使一边做对也会抄下来。通常一个本子我是从前往后抄题目,从后往前抄答案,当然分开写也可以,这都不重要。然后原始积累一段时间之后,就可以进行积累和消耗的并行阶段:比如你积攒了50题了,就可以开始,每天规定自己做一部分(比如2道大题和5道小题,视自己的情况调整),做完去批改。
这么做的一个原因是市面上流传的各种模拟试卷质量并不是都很高。而且由于省份不同,其实题目的差别还是挺大的,再一个是要找自己觉得自己薄弱的题目重点刷,自己整理的题就可以满足这个要求,如果有朋友和你情况差不多的话,两个人也可以互相换题做,比较新鲜。比如我每次考数学大考之前,都随机找几道自己“收集”的题目中标注为计算量大的题目练一下,这样在考试之前就很有侧重地进行了复习。
我高三的时候,由于填空题错误率太高(我们没有选择题,填空题一题5分,一共14题,我曾经有一次考出了176/200的分数,其中填空题扣了20分,大题一共只错了4分,把我们数学老师都快气哭了。。)采取的是这样的措施:首先我通过参考书之类的东西,刷了几百道小题(一点也不多,因为每套填空题里都有送分的简单题……),然后用上面的方式抄下题目和答案,14题一组。每天做“一组”,做到这一组内所有题目全对为止。就是这样。。如果错了一题,就不干别的,刷下一组,直到全对。要知道14道填空题刷一遍还是需要近半小时的,何况我自己挑出来的题都还是有点难度的。于是有一天我整个晚自习都在做这个,做了五次方才成功……那一天我其它神马作业都没写成,因为刷完70道小题实在身心俱疲。。刚开始的几天很难熬,后来基本上就没什么错误率了。而且我是错题本上的题和新的题穿插着做的,不存在是因为错题本上的题做的次数多所以背下来答案的情况。最后高考的时候我20分钟就做完了所有选择题而且全对。我这个方法有点极端,我个人是不推荐的,因为高三时间太宝贵,而我们只要准备三门课,所以我敢花血本来练这个,所以我建议不要太为难自己,每天拿出时间来练一练,练到自己满意就好啦。
当然各省份由于比重不同情况不同,具体是否接受,如何实施这个建议还是要因人而异哈~
(2) 会写的题写!不!完!
题主妹妹目前这种情况,不管是不是考试的时间分配问题,我都有这么一个建议:每一周(或者任何你觉得合适的频率)挑出一个完整的时间,做一份数学模拟卷。找和本省份题目风格一致或者专门为此出的模拟题,我记得有个叫什么金考卷之类的东西每个月出新试卷,也是按省出的吧,这样可以有效避免“题刷完了怎么办”的问题。总之有了题的来源,就开始做模拟卷吧~
首先要计时。自己戴着表或者看着钟做,全真模拟。时间一到,不管做到哪儿,都停下来,开始批改。整个过程,包括检查,如何跳题,都用考试的态度对待。几次下来,对自己时间分配的认识就会深一些了。这个方法是我刚开始准备数学竞赛的一卷的时候用的。最后我觉得自己在考试的时候时间也押得比较准~和之前练过几次应该还是很有关系的~
每次批改的好处还有你可以看着自己的分数慢慢进步,相信我,只要你高三一直在努力,分数一定会慢慢提高的~给自己批改试卷的过程帮助你理解这些“参考答案”都是怎么来的,为什么一道题大家都没写出答案来有的人得8分有的人就只能得5分,对于这些重点摸清楚了,做题的时候你就觉得出题人在想什么自己心里都是有数的啦~
我在最后的tips里面还会给一些关于考试中如何跳过题的建议~也对时间分配不佳有一些帮助。
2 (y/x)指标低
既然是题不会做,那唯一的方法就是把它弄会了。一般比如知道自己圆锥曲线的题总是错,就去找对应参考书里的那种专题训练。一定要先自己思考,想不出来再看答案。给自己定一个时间,比如10分钟想不到正确的解法,就直接看答案。高三时间太宝贵,以至于没任何必要在任何一道题上死磕。看答案是认真读参考答案,搞明白答案每一步的目的都是什么,是怎么环环相扣。最后合上答案自己做一遍。做出来了,皆大欢喜,没做出来,看看自己卡在哪一步,答案是怎么处理的,怎么就忘记了呢,再看一遍,再做……如果这题你看了一遍答案再做还是错了或者不会,就有必要抄下来,过个一礼拜自己再做一次~这样看到类似的题目印象一定就比较深啦。
此外我觉得各个参考书里的专题训练里的题其实并不太好,最好的题还是真题和模拟卷里的题。专题训练里的题好多给人的感觉都是为了凑够题数乱放在里面的……啊这是个人意见。
很多情况下,做不出一道题,那就想办法得更多的分。比如还剩个半小时结果试卷上愣是一题会做的都再也找不出了,那就认准一道题,把所有能得到的结论都写出来,一个是这样说不定就电光火石发现了这些结论之间的联系,推导出了最后的结论,另一个是,这么多结论虽然你看不出和所求的东西的关系,总有一些是重要的中间量,能拿点分吧~~~比如圆锥曲线题,看了半天还是不会做,至少先把题目中的所有线段长度能求出来的求出来吧~给了一个椭圆上的点,把“这个点到两焦点的距离长度为定值”的式子至少写摆出来吧,总会有个小一两分的~千万不要空着什么都不写~比如最后一道类似函数的题,怎么都写不出来,如果求极值,和导数有关,就先把导数求出来吧~~至于导数=0的方程不会解,那再说~~反正就是能做到哪儿就做到哪儿~~
到了高三的阶段,我个人觉得再去大幅度提高数学知识可能性太小,但是至少可以不要让自己失去本来该得的分数~
英语
有人在评论里说期待英语的部分我压力好大。。因为我本人英语学得不是很好T_T(为了回答这个问题,我刚才专门找了几道高考英语单选题,发现自己还是做不对,摔!这东西到底有什么用!)。
我高三也突击了一下英语。简单地提几点觉得还是有效的方法吧~
1 我英语也有一个小本子。虽然英语已经是非常有规则性的语言了,但是毕竟还是零碎的知识点很多。我们那个年代还是有单选的,不知道现在还有没,单选涉及很多以后你会发现根本不重要的语法问题,但是为了选出正确答案还是只能记下来然后反复看。还有比如什么hang in/hang out/hang on,break in/break through/break out等等这些带介词的固定搭配,总是考,神烦。。这些东西都集中整理好的话每次考试前就看看自己的这本笔记都足够应付了~
当然,笔记光看还是会忘。这时候我要强烈推荐一个神器叫做 玻璃纸 !!!!我当时就是拿了一张红色的玻璃纸,然后笔记上用普通的蓝色或者黑色笔写非重点,红色写重点,比如上面说的固定搭配,蓝色写英文,红色写中文,再比如虚拟语气/倒装的法则,重要的地方用红色写(比如语法环境用蓝笔写,应该用什么虚拟法则用红笔写)。这样首先在直接看的时候重点突出,其次,用红色玻璃纸盖住看的时候,就只剩蓝色的部分啦!然后你就看着英文说中文,看着语法环境说应该用的规则,等等等等,总之可以自己测试自己啦!原来总觉得反复看笔记,似乎合上笔记就忘了,也不知道如何测试自己到底记下来没有,自从有了神奇的玻璃纸,再也不用担心看笔记一会儿就忘记啦~
2 作文。据说要用高级词汇!
这一点似乎全国统一的,如果使用了高级词汇,得分就会高。。
所以,背一些高级词汇和高级句子吧~可以网搜“四六级作文高分词汇/句子”,找那些觉得自己能理解的或者至少背不错的,背几个这样的句子本身也对英语学习有帮助。而且四六级的好词好句拿来高考既有逼格又不至于太难导致hold不住。
不过可惜四六级英语还是chinglish。。想提高英语水平也是漫漫长路。。如果拿托福作文高分句子的话,似乎大材小用了而且高中生不一定能掌握好,所以我想了半天,还是四六级吧……
然后词汇就是比如用essential之类的词替代important,或者有一些高逼格的词语网上一搜都会有,也不用全换成高级的,中间换两个点缀一下就行了,毕竟高考嘛。。
但是,我印象中如果作文里出现了一个词拼错就是灾难性的,所以不确定的词情愿不要写~
还有一定要写得整洁~漂亮的卷面总是不吃亏的呀~
3 针对性训练?
这里纯粹是我的个人看法了,我觉得阅读理解这个东西,如果不是读不懂,实在没什么好训练的,因为高中阅读理解还是相对短的,只要阅读速度跟上题目没有做不出来的道理。想象一下那些题全翻译成中文,简直就是小学生智力题嘛!所以做题不是关键,阅读和理解才是关键。这方面我觉得只要训练自己阅读和理解英语的水平就好,高三时间比较宝贵,所以我本人选择的是牺牲训练阅读理解的刷题时间,重点刷了单选和完形填空。然后也利用休息时间读一读英文的各种材料,哪怕是阅读理解的文章也行,通常学校会给我们订一些英语报之类的东西,也行。我觉得只要阅读理解的文章读完了,知道在讲什么了,题是做不错的,所以练阅读就好,可以省下做题时间。当然,高考题总有一些奇怪的模棱两可的题,但是是少数,真碰到这种题,也只能认栽啦。
下面是一些应试的小技巧~与学科无关,希望能对题主的高三生活有帮助~
1 上面提到的玻璃纸~真的是神器~可以用在各个学科的自我测试上。比如化学这种知识点也很零碎的学科,也可以这么搞~
2 上面说的计时做模拟卷,也是适用于所有你觉得时间把握不好的科目的~
3 考试时间不够用的时候要果断跳过题,往下做。多次全真模拟之后就会把握好自己的节奏。我跳题的时候会在题号上做标记。比如一道题我算出来是一个奇怪的分数,什么十七分之十九的,十有八九是算错了,就做个标记,表示此题需要验算。当然没时间就只能算了,有时间的话一般也不够全检查一遍的,就把标记的题验算了就好。或者有一些题,你看完觉得自己肯定反正也做不出了,也标记一下,就是做完了之后回头写之前空的题的时候,也依然跳过此题的意思。这样可以高效利用考场上的时间。还有就是,快收卷的时候,看看自己后面还有一道大题没做,怎么办。。我自己考试的时候对时间押得很固定,剩20分钟的时候,不管后面还有多少没写的,一般都直接回头把之前还没做完的或者要验算的小题搞定,再继续写大题,大题毕竟可以写到哪儿算哪儿,何况最后剩的大题本来可能也做不完。算个大概,拿点分是点~
4 记好看的笔记。这一点特别适合女孩子~~~我当时和我的几个好闺蜜们就都喜欢用各种颜色的做总结用的小笔记本,买好看的本子用彩色的笔,然后努力写好看的字,写了这样的笔记自己都爱不释手,恨不得天天看才开心呢~~~而且还可以互相换着看,写得整洁好看别人才看得懂看得清楚,才愿意和你换嘛~这样就看到了更多人的总结和笔记。我有两个很铁的朋友比我高一届,她们把自己当年的笔记本也都送给了我,我也从头到尾过了一遍,觉得也非常有用。
5 放轻松。有人会告诉你“X模的成绩和最后高考的成绩基本上是一致的”。都是瞎说的,别理他们。有人会说“XXX的人一般最后都考不好/考得好”,也是瞎说,别多想。高考期间,多和自己的好朋友说说话,聊聊天,调侃调侃试卷,调整好自己的心态。而在准备高考期间,为自己找一些乐趣。找一群志同道合兴趣相投的好战友,高考这一仗会打得精彩又愉快。
6 如果有理想的学校,就激励一下自己。很多人在高考前都有dream school,在自己的笔记本扉页写一些鼓励自己的话和和理想有关的东西~对笔记有了感情,看过了之后的印象也会深哒~~
希望能帮到题主和大家~我觉得应付考试不可怕,也不难,只要找到核心和技巧。真正的学习知识才是苦难的。应试技巧的目的是在你已有知识一定的前提下最大化发挥出来的程度。但你的实际能力才是真正的瓶颈,所以还是要努力提高最本质的姿势水平呢~在中国高考是大多数人要面对的现实,那就应该最大化效率准备考试,既不要从高一就紧张兮兮,也不要到了高三还吊儿郎当,对自己负责,为自己的未来争取更广阔的空间。
这里讲的方法都比较具体,因为都是自己实践过觉得有效的,空话套话太多了,如果说空话套话大家说出来应该都差不多,也不用我来回答这个问题了。所以上面的方法可能都有一定的局限性,不能放之四海而皆准,到了高三还是尽量不要改变自己的风格,如果我说的有哪点你觉得可以采纳,那我真是非常开心·
此外,毕竟离我参加高考的年代已经过去4年多了,尤其是作文这种东西,潮流变了可能技巧就不一样了,所以如果有比我小的同学们看到有和当前潮流已经不符合的东西,也敬请指出,以免误导了别人,谢谢啦~
---分割线---
没想到写了这么长~~~回忆了一遍高中生活,年轻真好~
虽然对于我来说,高考是不情愿参加的,开头一个月,每每想到自己要高考都感到绝望,根本不知道自己还会不会考试,何况刚开始的模考成绩还不理想。但是回过头来看看,想起来的都是很温暖的事情,怎么和好基友好闺蜜们传纸条有时候说八卦有时候讨论数学题;怎么早自习迟到还偷偷在底下吃早饭;怎么跑到食堂去偷偷给好朋友庆祝生日;那一年我们高考倒计时在教室前面放了一个日历,每天撕一页,不同的人来保存,我认领了我生日那一天的,因为大家都知道那天是我的生日,谁也不和我抢;放学路上陪我走过的人,夏天晚自习下课吹来的风……这些有趣而美好的事情成为了我备战高考的符号,至于刷了多少题扣了多少分,什么都不记得啦~~~
再次感谢所有帮助过我的人,感谢所有和我一起参加过高考的人,感谢读到这里的你,如果能帮助到你,我将非常荣幸~~~
jQuery字定义动画animate() - 许全通 - 博客园
$(function () {
$("#panel").click(function () {
//三种动画同时进行
//$(this).animate({ left: "+=500px",height:"+=500px",width:"+=500px"}, 2000);
//三种动画顺序执行
$(this).animate({ left: "+=500px"}, 50);
$(this).animate({ height: "+=500px"}, 50);
$(this).animate({ width: "+=500px" }, 50);
});
});
</script>
链式方式(动画队列):$(function () {
$("#panel").css("opacity", "0.5");
$("#panel").click(function () {
$(this).animate({ left: "400px", height: "400px", opacity: "1" }, 2000)
.animate({ top: "200px", width: "400px" }, 2000)
.fadeOut("slow");
});
});
</script>
动画回调函数(callback):需要注意的是,css()方法不会加入到动画队列中个,而是立即执行。此时可以使用animate方法的最后一个参数callback;使用回调函数(callback)可以对非动画方法实现队列,只要将css()方法写在某个动画中的回调函数里即可!例如:$(function () {
$("#panel").css("opacity", "0.5");
$("#panel").click(function () {
$(this).animate({ left: "400px", height: "400px", opacity: "1" }, 2000, function () { $(this).css("border", "5px solid blue"); })
.animate({ top: "200px", width: "400px" }, 2000, function () { $(this).css("background-color", "Green"); })
});
});
</script>
注意:callback回调函数适用于jQuery所有的动画效果方法!!停止元素的动画: 方法:stop([clearQueue],[gotoEnd]); 参数:clearQueue:boolean值,表示是否要清空未执行完的动画队列; gotoEnd:代表是否直接将正在执行的动画跳转到末状态; 这两个参数都是可选参数!!判断元素是否处于动画状态: 语法: //如果当前元素(id=panel)没有进行动画,则添加新的动画!
}
延迟动画: 在动画执行的过程中,如果相对动画进行延迟操作,可使用delay()方法;用法如下:$(function () {
$("#panel").css("opacity", "0.5");
$("#panel").click(function () {
$(this).animate({ left: "200px", height: "300px", opacity: "1" }, 2000, function () { $(this).css("border", "5px solid blue"); })
.delay(2000)
.animate({ top: "200px", width: "300px" }, 2000, function () { $(this).css("background-color", "Green"); })
.delay(2000)
.fadeOut("slow");
});
});
</script>
jQuery中的其他动画方法: ->toggle(speed,[callback]); ->slideToggle(speed,[easing],[callback]); ->fadeTo(speed,opacity,[callback]); ->fadeToggle(speed,[easing],[callback]); ①toggle(): toggle方法可以切换元素的可见状态,如果元素当前是可见的,则切换为隐藏的,如果是隐藏的,则切换为可见的; ②slideToggle(): 此方法通过高度变化来切换匹配元素的可见性;效果和toggle相同,不过这个动画是调整元素的高度来显示和隐藏元素的,相当于slideDown和slideUp; ③fadeTo(): 此方法把元素的不透明度以渐进的方式调整到指定的值,值调整不透明度,元素的高度和宽度不变! ④fadeToggle(): 通过不透明度变化来切换匹配元素的可见性,值调整不透明度,相当于fadeOut和fadeIn;总结:| 方法名 | 说明 |
| hide(),show() | 同时修改多个样式属性:高度、宽度、不透明度 |
| fadeIn(),fadeOut() | 只改变不透明度 |
| slideUp(),slideDown() | 只改变高度 |
| fadeTo() | 只改变不透明度 |
| toggle() | 用来代替hide方法和show方法,同hide,show方法 |
| slideToggle() | 用来代替slideUp和slideDown方法 |
| fadeToggle() | 用来代替fadeIn和fadeOut方法 |
| animate() |
自定义动画的方法,以上各种动画方法实质内部都调用了animate方法,此外,直接使用animate方法
还可以自定义其他样式属性。也就是说,可以用animate代替其他所有的动画方法;
|
定义和用法
animate() 方法执行 CSS 属性集的自定义动画。
该方法通过CSS样式将元素从一个状态改变为另一个状态。CSS属性值是逐渐改变的,这样就可以创建动画效果。
只有数字值可创建动画(比如 "margin:30px")。字符串值无法创建动画(比如 "background-color:red")。
注释:使用 "+=" 或 "-=" 来创建相对动画(relative animations)。
语法 1
$(selector).animate(styles,speed,easing,callback)
| 参数 | 描述 |
|---|---|
| styles |
必需。规定产生动画效果的 CSS 样式和值。 可能的 CSS 样式值(提供实例):
注释:CSS 样式使用 DOM 名称(比如 "fontSize")来设置,而非 CSS 名称(比如 "font-size")。 |
| speed |
可选。规定动画的速度。默认是 "normal"。 可能的值:
|
| easing |
可选。规定在不同的动画点中设置动画速度的 easing 函数。 内置的 easing 函数:
扩展插件中提供更多 easing 函数。 |
| callback |
可选。animate 函数执行完之后,要执行的函数。 如需学习更多有关 callback 的内容,请访问我们的 jQuery Callback 这一章。 |
语法 2
$(selector).animate(styles,options)
| 参数 | 描述 |
|---|---|
| styles | 必需。规定产生动画效果的 CSS 样式和值(同上)。 |
| options |
可选。规定动画的额外选项。 可能的值:
|
通过浏览器直接打开iOS/Android App 应用程序 - Cundong's log - 开源中国社区
点击浏览器中的URL链接,启动特定的App。
首先做成HTML的页面,页面内容格式如下:
<a href="[scheme]://[host]/[path]?[query]">启动应用程序</a>
这一句就可以了。
各个项目含义如下所示:
scheme:判别启动的App。 ※详细后述
host:适当记述
path:传值时必须的key ※没有也可以
query:获取值的Key和Value ※没有也可以
作为测试好好写了一下,如下:
<a href="myapp://jp.app/openwith?name=zhangsan&age=26">启动应用程序</a>
接下来是Android端。
首先在AndroidManifest.xml的MAIN Activity下追加以下内容。(启动Activity时给予)
※必须添加项
<intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="myapp" android:host="jp.app" android:pathPrefix="/openwith"/> </intent-filter>
HTML记述的内容加入<data …/>。
其中必须的内容仅scheme,没有其他内容app也能启动。
※注意事项:intent-filter的内容【android.intent.action.MAIN】和 【android.intent.category.LAUNCHER】这2个,不能与这次追加的内容混合。
所以,如果加入了同一个Activity,请按以下这样做,否则会导致应用图标在桌面消失等问题。
<intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="myapp" android:host="jp.app" android:pathPrefix="/openwith"/> </intent-filter>
这样的话,没有问题。
接下来在Activity中需要取值的地方添加以下代码,我是直接写在OnCreate函数里的:
String action = i_getvalue.getAction();
if(Intent.ACTION_VIEW.equals(action)){
Uri uri = i_getvalue.getData();
if(uri != null){
String name = uri.getQueryParameter("name");
String age= uri.getQueryParameter("age");
}
}
这样就能获取到URL传递过来的值了。
——————————————————————————————————我是分割线————————————————————————————————————
代码copy完了,是不是很惊奇的发现用浏览器输入
myapp://jp.app/openwith?name=zhangsan&age=26
是不是404,打不开?
楼主你这不是骗人么!楼主你个混蛋啊。
客官,稍安勿躁啊,你看看你用的浏览器是什么?UC,猎豹,欧朋?放弃吧,试试系统自带浏览器或者谷歌浏览器吧。肯定能成功的,不能成功的话再来坑我。哈哈。
——————————————————————————————————我是分割线————————————————————————————————————
突然觉得好悲哀,好不容易get了这个技能,却不能被第三方浏览器使用。在这个android浏览器大部分被第三方占据着的时代不得不说是个悲剧啊。
接下来还是说说为什么第三方浏览器不能成功吧。首先,我发现的是UC浏览器,如果你使用了自己的scheme,而不是http的话,uc会默认在你的scheme前面添加http://。这太坑爹了。其他浏览器没看是不是同样的情况。发现这个问题后我就试着把自己的scheme换成http。然后满怀期待的又跑了一遍,结果还是坑爹了。所以我想会不会是第三方浏览器对url做了处理。到这里,我也无可奈何了。我测试了UC,猎豹,欧朋,这3个都不支持。系统自带的和谷歌浏览器是支持的。
最后再补充个线索吧,在浏览器里搜索百度应用。进了他们的页面后,他们是可以实现在各种浏览器启动已经安装好的本地app的。看到这个后我就看了下他们页面的源码。
在这里他们页面添加了个data-sentintent的标签,看到这里,应该能确定第三方浏览器应该是默认都不支持发intent的,只能自己起一个。根据前端说,这个标签应该是自定义的。我们前端看源码的时候发现是这样的
所以最后的结果应该是百度这边是起了个端口,然后在应用里启用了一个服务,来监听这个端口,来获取这个intent。大概就这个思路了。不过楼主没有实际去操作。项目时间紧,太麻烦了。对了,百度这个是有集成他们inapp这个sdk的。
再附上stackoverflow两个相关链接:http://stackoverflow.com/questions/3469908/make-a-link-in-the-android-browser-start-up-my-app
http://stackoverflow.com/questions/2958701/launch-custom-android-application-from-android-browser
最近遇到这么一个需求:
当用户在手机浏览器中点击一个按钮时,如果手机上已经该应用程序,则直接打开,如果没有安装,则转向应用下载页面。 再详细一点就是:通过点击网页中一个按钮,打开本地某个Activity(如果有的话)或用浏览器打开某个url。
查了一下文档,Android是支持这个的:
http://developer.android.com/guide/topics/manifest/data-element.html
解释一下文档中的描述:scheme://host:port/path or pathPrefix or pathPattern
这里面定义的schema+host+port+(path or pathPrefix or pathPattern)能拼凑出一个http链接,包含这个filter的Activity,能处理这个http链接。
实现:
- 网页代码
点击这个按钮:
|
1
|
<a id="applink1" href="http://test.xx.com/demo/test.php">打开</a> |
在 http://test.xx.com/demo/test.php中,直接请求xxxx.apk下载。
- Activity代码
给目标Activity增加以下filter:
|
1
2
3
4
5
6
7
8
9
10
11
|
<intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:host="test.xx.com " android:path="/demo/test.php" android:scheme="http" /> </intent-filter> |
增加该filter后,该Activity就能处理 http://test.xx.com/demo/test.php。在浏览器中点击“开始”,发起对该URL的请求时,如果本机安装了这个应用,系统就会弹出一个选择,询问你想使用浏览器打开,还是使用该应用打开,如下图:

如果本机没有安装这个应用,则直接会使用浏览器打开 http://test.xx.com/demo/test.php,又因为该页面中直接请求了XX.apk,浏览器会提示你下载应用,如下图:



