2025-01-16 08:13:32
In the application scenarios of Elasticsearch, the storage of large amounts of data may significantly impact the read and write performance of Elasticsearch. Therefore, it is necessary to split indexes according to certain data types. This article explains through relevant technical research whether splitting data on Elasticsearch will affect query results in AI search scenarios. It also compares the implementation principles of other vector databases currently available in the industry with those currently using Elasticsearch.
Elasticsearch vs. Milvus: Comparison in AIC use cases
Investigate the data storage mechanisms and query processes of mainstream vector databases in the current industry (Qdrant, Milvus). Conduct an in-depth analysis of how they handle data updates (such as incremental updates and deletion operations) and compare them with Elasticsearch.
The impact of single-table and multi-table design on similarity calculation in the Elasticsearch BM25 model
Study the Elasticsearch differences between single-index and multi-index structures in the BM25 calculation, particularly their impact on efficiency and accuracy during calculations.
Elasticsearch architecture is straightforward. Each node in a cluster can handle requests and redirect them to the appropriate data nodes for searching. We use blue-green deployment for scaling up or down, which enhances stability requirements.
Cons: Currently, we only use two types of Elasticsearch nodes: data nodes and master nodes. Every data node serves all roles, which may not be as clear-cut as Milvus’s architecture.
The Milvus Lite is the core search engine part with the embedded storage for local prototype verification. It’s written in Python and can be integrated into any AI python project.
The Milvus standalone is based on Docker compose with a milvus instance, a MinIO instance and an etcd instance. The Milvus Distributed is used in Cloud and production with all the required modules. In the most case, we are talking about the Milvus Distributed in this report.
Milvus has a shared storage massively parallel processing (MPP) architecture, with storage and computing resources independent of one another. The data and the control plane are disaggregated, and its architecture comprises four layers: access layer, coordinator services, worker nodes, and storage. Each layer is independent of the others for better disaster recovery and scalability.
Even in a minimal standalone Milvus deployment. We need an OSS service like Minio or S3, A etcd standalone cluster and a milvus instance. It’s quite complex architecture and mainly deployed and used on K8S.
Elasticsearch | Milvus | |
Complexity | Simple, only master nodes and data nodes. | Complex, require OSS, etcd and different types of milvus nodes. But can be deployed by using Amazon EKS. |
Potential Bottleneck | As the increase of the number of Elasticsearch cluster. We may need more replicas to balance the query for avoiding hot zone. | Etcd requires high performance disk for better serving metadata. It could be a bottleneck when the query increases. Files on object storage need to be pulled to the local disk and eventually loaded into memory for querying. If this process switches frequently, the performance may not necessarily be good. |
Scaling | Require blue-green deployment to get the online cluster to be scaled | Easy to scale on k8s. The compute node instance number can be changed on demand. |
Storage | Every data node’s hard disk. Require to add new data node to increase the storage. S3 is only used as the backup storage. | OSS based. S3 can be used for storage all the metrics. |
AA Switch | Require two identical Elasticsearch cluster. | No need to AA switch. Just reload the query nodes or add more query nodes. |
Upgrade | Same as the scaling. | Use helm command on k8s cluster. |
In this diagram, we can see how a new document is stored by Elasticsearch. As soon as it “arrives”, it is committed to a transaction log called “translog” and to a memory buffer. The translog is how Elasticsearch can recover data that was only in memory in case of a crash.
All the documents in the memory buffer will generate a single in-memory Lucene segment when the “refresh” operation happens. This operation is used to make new documents available for search.
Depending on different triggers, eventually, all of those segments are merged into a single segment and saved to disk and the translog is cleared.
This diagram shows the whole routine for a simple index request.
The picture above shows all the modules used in data writing. All the data writing requests are triggered in the SDK. The SDK send the request through the Load Balancer to the proxy node. The number of the proxy node instances could be varied. The Proxy node cached data and request the segment information for writing the data into the message storage.
Message storage is mainly a Pulsar based platform for persistence the data. It is the same as the translog in Elasticsearch. The main difference is that Milvus don’t need a MQ service in the frontend. You can directly write data through it’s interface. And don’t need bulk request in Elasticsearch.
The data node consumes the data through message storage and flush it into the object storage finally.
As we can see from the diagram, Elasticsearch shards each Lucene index across the available nodes. A shard can be a primary shard or replica shard. Each shard is a Lucene Index, each one of those indexes can have multiple segments, each segment is an complete HNSW graph.
Milvus provides users with the largest concept called Collection, which can be mapped to a table in a traditional database and is equivalent to an Index in Elasticsearch. Each Collection is divided into multiple Shards, with two Shards by default. The number of Shards depends on how much data you need to write and how many nodes you want to distribute the writing across for processing.
Each Shard contains many Partitions, which have their own data attributes. A Shard itself is divided based on the hash of the primary key, while Partitions are often divided based on fields or Partition Tags that you specify. Common ways of partitioning include dividing by the date of data entry, by user gender, or by user age. One major advantage of using Partitions during queries is that if you add a Partition tag, it can help filter out a lot of data.
Shard is more about helping you expand write operations, while Partition helps improve read performance during read operations. Each Partition within a Shard corresponds to many small Segments. A Segment is the smallest unit of scheduling in our entire system and is divided into Growing Segments and Sealed Segments. A Growing Segment is subscribed by the Query Node, where users continuously write data until it becomes large enough; once it reaches the default limit of 512MB, writing is prohibited, turning it into a Sealed Segment, upon which some vector indexes are built for the Sealed Segment.
A stored procedure is organized by segments and uses a columnar storage method, where each primary key, column, and vector is stored in a separate file.
Both Elasticsearch and Milvus require memory to load vector files and perform queries. But Milvus offers a file-based index type named DiskANN for large datasets, which doesn’t require loading all the data but indexes into memory for reducing the memory consumption.
As for Elasticsearch, the dense vector on HNSW is the only solution. The default dimension is float. But Elasticsearch provides the optimized HNSW for reducing the size or increase the performance. To use a quantized index, you can set your index type to int8_hnsw
, int4_hnsw
, or bbq_hnsw
.
Supported index | Classification | Scenario |
FLAT | N/A |
|
IVF_FLAT | N/A |
|
IVF_SQ8 | Quantization-based index |
|
IVF_PQ | Quantization-based index |
|
HNSW | Graph-based index |
|
HNSW_SQ | Quantization-based index |
|
HNSW_PQ | Quantization-based index |
|
HNSW_PRQ | Quantization-based index |
|
SCANN | Quantization-based index |
|
The query phase above consists of the following three steps:
The distributed fetch phase consists of the following steps:
GET
request to the relevant shards.In the reading path, query requests are broadcast through DqRequestChannel, and query results are aggregated to the proxy via gRPC.
As a producer, the proxy writes query requests into DqRequestChannel. The way Query Node consumes DqRequestChannel is quite special: each Query Node subscribes to this Channel so that every message in the Channel is broadcasted to all Query Nodes.
After receiving a request, the Query Node performs a local query and aggregates at the Segment level before sending the aggregated result back to the corresponding Proxy via gRPC. It should be noted that there is a unique ProxyID in the query request identifying its originator. Based on this, different query results are routed by Query Nodes to their respective Proxies.
Once it determines that it has collected all of the Query Nodes’ results, Proxy performs global aggregation to obtain the final query result and returns it to the client. It should be noted that both in queries and results there exists an identical and unique RequestID which marks each individual query; based on this ID, Proxy distinguishes which set of results belong to one specific request.
Hybrid Search has long been an important method for improving the quality of Retrieval-Augmented Generation (RAG) search. Despite the remarkable performance of dense embedding-based search techniques, which have demonstrated significant progress in building deep semantic interactions between queries and documents as the model scale and pre-training datasets have expanded, there are still notable limitations. These include issues such as poor interoperability and suboptimal performance when dealing with long-tail queries and rare terms.
For many RAG applications, pre-trained models often lack domain-specific corpus support, and in some scenarios, their performance is even inferior to BM25-based keyword matching retrieval. Against this backdrop, Hybrid Search combines the semantic understanding capabilities of dense vector search with the precision of keyword matching, offering a more efficient solution to address these challenges. It has become a key technology for enhancing search effectiveness.
BM25 (best matching) is a ranking function used by search engine to estimate the relevance of documents to a given search query.
Here is BM25 calculation formula for a query
IDF (inverse document frequency) weight of the query term
A term that appears in many documents does not provide as much information about the relevance of a document. Using a logarithmic scale ensures that as the document frequency of a term increases, its influence on the BM25 score grows more slowly. Without a logarithmic function, common terms would disproportionately affect the score.
By default, Elasticsearch calculates scores on a per-shard basis by leveraging the Lucene built-in function org.apache.lucene.search.similarities.BM25Similarity
. It’s also the default similarity algorithm in the Lucene’s IndexSearcher
. If we want to get the index level score calculation, we need to change the search_type
from query_then_fetch
to dfs_query_then_fetch
.
In dfs_query_then_fetch
search, we will add the org.elasticsearch.search.dfs.DfsPhase
in searching. It will collect all the status in DfsSearchResult
which contains the shards document information and hits, etc. The SearchPhaseController
will aggregate all the dfs search results into a AggregatedDfs
to calculate the score. We can use this search type to get a consistent BM25 score across multiple index.
The only difference between multiple indexes or shard based BM25 calculation is the IDF. But if the data are well distributed among all the indexes and the document count are large enough in every shard. The difference for IDF could be tiny because we use logarithmic. You can get the growth trend in the second chart above. In this scenario, we don’t need to use dfs_query_then_fetch
to calculate the global BM25 which requires more resource to cache and calculate.
Starting from version 2.4, Milvus supports sparse vectors, and from version 2.5, it provides BM25 retrieval capabilities based on sparse vectors. With the built-in Sparse-BM25, Milvus offers native support for lexical retrieval. The specific features include:
2025-01-05 23:20:32
去年年底,我和老婆一起参加了她好友的婚礼,同席的都是女方的朋友,其中有两对夫妻刚刚有了孩子,大家在讨论宝宝怎么还不会抬头翻身。此时,我和老婆相视一笑,眼角里满是默契。
当有女儿时,我和老婆就开始焦虑。人家宝宝三个月就能翻身,怎么我女儿到现在还只会抬头,大动作是不是有些滞后?睡觉时,一定要给她换着侧睡,千万别让她得舟状头畸形。接着,当要开始学走路时,我又开始焦虑,别人家的宝宝早就能爬了,可我这女儿怎么都不会满地爬。快到一岁时,我又开始焦虑,怎么还不会说话,只能吐出简单的字词,而别人家的宝宝已经能背唐诗了。就这样,我们在一个又一个所谓的“应该会”中焦虑着……
三年后的今天,再回头看当初的焦虑,不仅觉得有些好笑,笑我们当时对每个时间点的过度关注,也笑我们对成长的无知。比如翻身这样的动作,等女儿对这个世界的好奇超越了仰视的范围后,某个晚上,在睡前玩耍时,她自然而然地翻了个身,看向了另一边。而她在客厅里开始站起来用“围栏”磨牙后,便学着扶着围栏走,后来脱离围栏,现在已经能在家里满地爬上爬下。可见,宝宝每一次的成长,都不是简简单单一蹴而就的,而是由许多微不足道的积累构成。而当时的我们,既过度关注结果,也忽视了过程中应该做的引导。直到后面,女儿一次又一次地在不经意间给了我们惊讶,也让我们有了新的认知。
二〇二二年年底,老婆的好友送给女儿一辆自行车作为生日礼物。春天一到,我们便打算让女儿骑自行车。刚开始,女儿是抗拒的,嘴里说着:“不要,我不想骑。”后来,我们无奈地把自行车放在客厅她的玩具边上,希望她能出于好奇心想去骑。三月,阳光明媚,小区里也有孩子出来玩和骑车。女儿突然提出:“我想要骑自行车。”起初,她不会蹬脚踏,加上她是个急性子,每次都是反方向狂蹬,但自行车丝毫不动。无论怎么引导她,都无济于事,我们只能无奈地看着。五月,芜湖市花月季花开,花丛中一片淡粉色。某天早上,我们收到了母亲发来的视频,视频中女儿骑着自行车沿着月季花坛前进,她的动作是往前踩一点,再把脚踏往回踩,再往前踩一点,周而复始。相比以前完全不会骑车,她已经进步了不少。到了十月,家边的青弋江水位下降,露出了浅滩的石块。此时,女儿也能在江堤上蹬着脚踏车骑行,速度飞快。
女儿在我们眼皮底下日日成长,似乎没有什么变化,但又真的是一天一个样。某天晚上,家庭微信群里出现了一张照片,照片中是家门口的地垫,本来放在鞋柜底下的爷爷的拖鞋现在被整齐地摆放在地垫上。再一问才知道,女儿因为知道爷爷今天周五要回家,提前偷偷把鞋子摆在门口等他。这件事没人教过她,但她做到了,让人既暖心又欣喜。后来,她还把老婆下班前的鞋摆得整整齐齐,再后来,是我的鞋。上周末,我和女儿说:“鞋子要把鞋口朝外,这样回家的人才好穿。”周五傍晚,妈妈发来了新的照片,三双鞋整整齐齐地摆在门口。那一刻,我的心里百感交集。
十年前,我读林志颖的《我对时间有耐心》时刚刚大学毕业,无法体会林志颖当初对于 Kimi 的种种焦虑和后来的坦然。如今,审视与女儿一同成长的这三年,短暂而又漫长。虽然我日子过得粗糙,已经很少有心情和时间记录下这些让我触动的瞬间,但在合肥工作时偶尔想起,心里便会涌起一股温暖。女儿教会我和老婆最多的便是重新认识成长——这个我们自己亲身经历的事情,因为时间的冲刷而忘却,现在通过养育下一代重新习得,这何尝不是一种“成长”。
我想人生大概如此吧,充满矛盾,不断获得,又不断失去,有优雅也有许多挣扎。就像是一场即兴表演,哪有什么主题可言呢?走着走着,就到了。
2025-01-05 05:49:32
继《文学报》停刊之后,《书城》杂志也宣布休刊,而《上海文化》也已无法订阅。这一报两刊作为上海文学的重镇,自创刊至今已逾四十年,遗憾未能挺过 2025 年的新年钟声。我是它们的读者,21 年开始居家办公后,逐渐养成订阅的习惯。每周四下午到小区门卫取《文学报》,内心充满欣慰。在这个纸质书逐渐淡出日常的当下,一份文学报显得如此珍贵且不合时宜,而它坚持到了今天,我倍感欣慰。
《书城》以各类知识性的随笔散文见长,是我每年都珍藏的杂志。与《读书》和《读库》相比,它更注重趣味性,随笔体的风格读来令人愉悦。而《上海文化》则是我心中极为敬重的纯文学评论杂志,聚焦当代文学,尤其对新人的关注令人钦佩,远胜《小说评论》。其编辑张定浩、黄德海等人以开放多元的文学趣味,不断捕捉文坛动态,在批评与理论中别具一格,展现了鲜明的海派风格。
一报两刊的停刊,昭示着纯文学市场的进一步萎缩,以及电子化阅读的全面普及。作为纸质书的爱好者,我或许正成为时代中的少数派。资讯的发达与文学阅读的无纸化已是大势所趋,这并非悲哀,而是现实。毕竟,如今的读物不是稀缺,而是过剩。报刊杂志塑造了我们对文学的理解,甚至激发了读者的创作冲动。
当文学以物质形态退出生活,是否意味着文学已无处不在?《文学报》虽然不复存在,但文学依然延续,只不过转移到了手机等电子设备上。这种转移将塑造出怎样的文学形式,我难以预料。纸质书与报刊的存在,带给人们沉浸与珍视,而在屏幕上的滑动与点击却容易使人匆匆掠过。尽管信息更加丰富,但信息的过载是否也成了一种压迫?纸质文学的舒朗与留白,像有规律的饮食,是否更有助于心灵的平静与滋养?我不得而知。
今天的人们在现代生活中奔波忙碌,留给纯文学的时间愈发稀少。20 年前,或许因经济拮据无法购书,而如今在电子化时代,图书种类繁多且获取便捷,却反而有人不再阅读。时代的错位让我们跳过了一些东西,这种改变究竟是好是坏,我无从判断。
悼念这一报两刊的停刊,缅怀它们曾带来的愉悦与思考,但文学本身不会“停刊”。
愿文学继续照亮我们的生命与灵魂。
2024-12-31 22:46:12
时代的浪潮滚滚向前,互联网的发展瞬息万变。我立于茫茫信息流之间,却难找昔日“网上冲浪”的痕迹。
——题记
时隔 8 年后再次登陆当当网后台,竟发现页面丝毫未变,也许它和淘宝网页版一样,早已被移动互联网取而代之。难能可贵的是,感谢它的不变,我还能找到最初的订单记录,一窥当时的故事。
订单中的最早记录始于 2008 年的寒假,是本高中数学竞赛的书。这本书已经随着我的搬家消失,而对应的购书缘由,我想了很久。拨开脑中一层层尘封的记忆,终于在今天上午这个明媚的冬日,忆起了那个明眸皓齿的她……
那个时候我刚上高一,家住在厦门的将军祠,旁边便是厦门最牛逼的高中之一——厦门一中。那里有个不错的小书店,叫科文图书,专门卖一些特定的教辅书、竞赛用书。我在当当网买的这本书,最初便是在这座线下书店购买的。
虽然我中考的分数可以报考厦门一中,但因为没有厦门户口,我实际上读的是厦大附属科技中学。每天的行程便是从将军祠坐旅游大巴去1小时开外的珍珠湾上学。这趟旅程漫长且枯燥,沿途的海景风光旖旎,久了也便失去了新鲜感,直到那一天的到来……
10 月的某个早晨,等车的我突然发现站台出现了熟悉的科中校服,而且是位姑娘。我好奇地走上前:“你好,你是科技中学的吗?”由此打开了话匣子。经过交谈得知,对方是因为父母工作刚刚转校来此的学生,目前在我校借读。往后的日子里,每天等车时,我都能看到她。那段公交旅途,便不再那么漫长了。有时候,公交车到了目的地,我竟觉得时间过得太快,心里不禁想着,为什么学校不能再远一点?
她很喜欢数学,当时的科技中学还没有竞赛相关的培训,但家边上的厦门一中,每年假期都有数学竞赛培训。我便和她约定好在寒假一起溜进一中旁听。一中使用的辅导书,我在科文书店只买到了一本,但还缺给她准备的一本。由此,我学会了网购和邮局汇款,几经周转买到了这本书。
寒假如期而至,但她却迟迟未到。我已不再记得在一中阶梯教室等她的那段时光,只记得自己把写有签名的线下购买的书提前给了她,说:“你先预习。”而这,竟是我和她的最后一次对话。
开学后,我再也没有在公交车站见到她。社恐的我,终于鼓起勇气,找到她的教室。才从她的同学口中得知,她在寒假时转学去了福州。
我最终还是没去参加数学竞赛,我把所有的时间都用于攻读化学。那本当当网购买的数学竞赛书,被我藏于某个角落,高中毕业后被父母当成废纸出售。它最终变成了纸浆,再也找不回来。
我终究不清楚那本借给她的书是否看完了。只记得那个不算冷的冬天,那个社恐的我,一个人坐在厦门一中的教室,周围熙熙攘攘,但世界与我无关。
2024-11-07 02:06:12
认识她时我十四岁,都刚上高中。今年我三十二岁,她三十三岁,都已经结婚。
刚刚认识她的时候我是新高一生,她是从学校初三直升上来的高一生,除了都是学生和读的是同一个高中以外没有任何相似之处,甚至她在楼上的班级,我在楼下的教室。她是厦门岛外生,所以是寄宿在学校,我是走读生,每天会坐公交经过漫长的环岛路回家。只有周末,她才有空回复我发的消息。高中的生活是很无聊的,特别是省重点高中的高中生,少量的休闲娱乐活动穿插在大量的课程作业考试里,但是即使是这样我还是有好多好多话要跟她说,说我的老师说我的同学说我的作业说我的考试,说我的理想我对世界的思考我对未来的憧憬,她总是耐心又认真地回应我,陪我说很多很多话,好像是在蹲下来回应一个小男孩的内心世界。
我高一下学期的时候开始忙着竞赛,开始周末往返于学校旁边的厦大和家。每次竞赛培训结束,我都会晃一晃昏昏沉沉的脑袋,去找她玩。学校后面是厦门音乐学校,和一整条小吃街,我们常常溜进音乐学校,偷偷摸摸地看里面的学生演奏,再装模作样的点评上一番。高二的时候分班,因为没有厦门户口,我被踢出尖子班和她同班。那个时候我就坐在她背后的座位,每天上课,当讲的都是我竞赛学过的内容的时候,我就坐在她背后,痴痴地望着她。
我高三的时候她谈了恋爱,那段时间我每周末打开 QQ 她都用的是不同的情侣头像。寒假的时候我终于敢开口问她是不是谈恋爱了,她很干脆地回答“是的”。但是这场恋爱好像没谈多久,暑假的时候她一度把头像换成了黑色,背景图也换成了很阴郁的图片,隔着屏幕都能感觉到她的颓废。知道她谈恋爱的时候我没觉得有多难过,但是看见她这个样子,这个我从没见过的样子,总觉得很心疼。
就这样,这三年里我走的每一步都有她的影子。如果我的高中生活是一篇论文的话,那关键词里一定有她的名字。
我和她表白是在高考结束后的那个暑假,在一个普通的晚上,上一秒我们好像还在聊着选专业之类的话题。其实我并没有打算表白的,不知道为什么那天就突然很想把自己的爱意告诉她。不出意外当然是被拒绝,但是这个过程依旧很温柔,很体面。她好像并没有很惊讶,只是说“对不起你”,她说“我一直很欣赏你,作为我的一个朋友”。我说我表白被拒绝太丢人啦,她说“没有很丢脸啊,而且你很勇敢啊”。她还说希望今后不管我去到哪个大学什么专业都能开心地过大学生活,希望我平时能更开心一些,希望我能好好的。
我要去很远的地方上大学了,我问她能不能在我走之前见见她,她欣然答应,好像也想见我一样,还说要送给我一个小东西。我们见了面,我握了握她的手,她送给我的小东西是一支钢笔。我们一起吃了一顿饭,饭后又一起走了很长的路。分别之际我问能不能抱一抱她,她笑着说这里有很多同校同学来来往往,看见了不好,最终也没抱成。她笑着看向我说“还是要加油啊”,我很用力地点点头。她走出去了几步,我突然问她“我们还会再见面吗?”她转身,也还是笑着看向我,点点头说会的。她要过一条马路,走到一半又转身对我挥挥手,然后走远了。
后来我去了离家很远的地方上大学,还是像上高中的时候一样,有什么新鲜事都要通过 QQ 告诉她,但是她不再回复了。很快大学的第一个寒假要来了,新年也要来了。北方的大学放寒假很早,赶在放假前我为她准备了一份新年礼物寄给她,给她发消息她还是没有回,那天晚上我哭了很久。就在我刚刚哭完的时候她的消息来了,难以描述那一刻我有多高兴。她说她很久没有回复我了,我发给她的各种图各种事她都有看到,但是她想我要在大学里有新的生活,我要去交新的朋友甚至谈恋爱,她不能继续在我的生活占很重要的位置,会耽误我,等我回家以后要带我吃饭。收到我的新年礼物她很高兴,激动地像个收到玩具的小朋友,每拆出来一件都要发给我看一看。
后面我们很少很少再说话。偶尔再有一些对话也没有了以前的轻松愉快,总是说着说着就要着急了,但是我们都没有真的生过对方的气。14 年底毕业的时候我实在没有忍住问了她的情况,她说挺好的,叮嘱我一个人在外面上学要照顾好自己。她开始说我是小屁孩,催我去谈恋爱,说她会耽误我。
距我们上次见面已经过去了十二年八个月二十一天,但距我上次见到她好像只过去了两天。
不知道从什么时候起她的朋友圈已经屏蔽我了,她结婚的消息我也是在别的地方听来的。其实我并不惊讶,我们也确实都到了该结婚的年纪了,但是我的反应还是很强烈,那段时间我不能听到结婚这个词,我甚至不能看见任何和结婚有关的东西,在微信里看见备婚攻略我都要立刻关掉手机,我不能想她结婚了这件事,我不能想到和她有关的任何事。
写到这里,我已经回忆了从我们认识到今天所有我记得的事,还有很多没有写出来。
说喜欢她太单薄了,说爱又太厚重,我至今也没有找到介于两者之间的词来形容我对她的情意。其实我刚刚知道她朋友圈屏蔽我的时候是非常难过乃至生气的,我甚至在凌晨给她发微信问她为什么要这么做,她只是很平静地说“看我朋友圈对你来说是在耽误你”。现在想想也是好事,因为让我某一天突然在朋友圈看到她的婚礼请柬和婚后的幸福生活对我来说还是太残忍了。
我突然在想我与她之间究竟是怎样的情谊。
青春期啊,有太多焦躁不安的情绪需要排解,有太多充沛的情感需要安放,于是我将这些都投射在她身上,连同我希望拥有的品质和对美好爱情的憧憬,也没有问过她是否愿意。
我千千万万次诚挚地祝福她能够永远健康快乐幸福,现在她既幸福又自由,这不就是我对她的祝福吗?
我总是太迷恋结尾,我总是想我喜欢她我要和她在一起,我总是不相信人与人之间的距离并非三言两语就可以悄然抹掉的。
我想我一辈子也忘不了她,因为我在年少的时候曾经那样执着、热烈、真诚地爱过她,因为我们之间曾经有过那样纯粹、体面、美好的情谊。
那么我衷心地祝愿她这一生要顺顺利利,要家庭美满,要平安健康,要永远幸福。
2024-10-17 04:47:12
你好,我是你的粉丝,我有一个问题很痛苦,就是我的英语问题。我的英语很差,甚至水平只停留在 26 个英文字母和少量常见的简单词汇。我无法记住这些长的单词和繁琐的语法,可能上一秒记住了,下一秒就会忘记。而且在使用语法时,我经常记不住这些语法该如何用。我也在网上找过办法,我尝试过每天早上都重复温习一些单词。但是反复的遗忘让我很难受,我无法接受我记不住这些东西的事实。我在高等数学中很容易能记住一些公式,也能很简单地记住一些题的解题方法,这证明我的记忆力和智商没有问题。我无论尝试任何办法,最后都是以失败告终。所以我想向你请教一下,你是如何学习英语的?有什么建议吗?非常感谢。
你好:
很高兴收到你的来信,回复得并不及时,还请见谅。关于英语学习的问题,我相信这是很多人常见的困扰。我们常常付出了比其他国家的人更多的努力,但在英语这门学科上总是觉得学不好。在看你的提问时,我注意到了几个细节,这几个细节还挺有意思,也是我想提醒你的。
语言是为了满足日常交流、思想传递等需求而诞生的,B 站有一个名为《语言起源之谜,人类的语言来自哪里?语言又是如何诞生?》的视频,里面提到了语言诞生的一种假说。通过观察我宝宝的学语阶段,我能明显发现,她首先是学会一些简单的字词,尤其是以简单元音为基础的发音。接着,宝宝开始模仿你说话,先是复述,再根据她的理解进行加工,来观察你的反应。通过和身边的人学话,最后进行较为初级的语言表达,慢慢加入逻辑和因果假设,这就是我们常说的“咿呀学语”。
现代语言学家在研究非母语学习时,提出了一个名为“二语习得论”的假说,这个过程大体上和母语学习类似,参考这篇文章了解更多。我们发现这个过程分为两个部分:习得和学得。儿童在语言黄金期时,通过“大量输入”能够轻松习得另一门语言。对于成年人来说,虽然不能像儿童那样轻松习得外语,但我们有更强的理解能力和逻辑思维能力,所以需要另辟蹊径。
那就是,通过“使用”的方式,而不是通过“学习”的方式来学习英语,English in USE。
语音是语言的关键基础,任何一门语言,首先都是通过听说来构建基本的语言感知。我们在中小学学英语时,往往以读写为基础,先教单词,告诉你意思,然后死记硬背单词的拼写。接下来是课文一篇篇地学习,抠语法细节。这其实是一种 hard way。语言是活的,对话是最灵活的使用场景。首先要多听、多讲,跟着复述并尝试加工,越日常、越贴近生活场景的对话练习越好。这也是为什么很多人在国外旅游或生活一段时间后,语言能力有极大提升的核心原因,因为你在不断地听说,并且用起来了。
听说是基础,但听对说对很难。因此,尽管我们强调听说的重要性,但正确的发音和听力是有效学习的关键所在。
最近家长们常常抱怨 2024 年后的英语教材很难,不教音标,但其实这反而是一种改进。音标本质上是符号化的元音和辅音表述习惯,这是一种语音学概念。现在如果我们去问一个讲普通话的人,请问汉语里面有多少辅音和元音,绝大多数人可能回答不上来,或者只能说出 a、o、e、i、u、ü 等几个有限的元音。我们虽然不知道具体的元音辅音,但通过拼音学习,基本能掌握汉字的普通话发音,这得益于我们从儿童时期开始的听力训练,也得益于我们能正确听出平舌音、翘舌音等发音区别。
因此,音标的学习并非必要,真正必要的是如何读出单词的正确发音。很多人推崇自然拼读法,但它的覆盖面有限,核心还是正确掌握英语元音和辅音的发音。对于母语是英语的人,他们自然通过家长和老师学习“英语拼音”来掌握发音,而我们作为汉语母语者,只能借助音标来学习“美音”或者“英音”。
英语发音和汉语不同,母语的熟练掌握会直接影响我们学习英语,最明显的就是发音问题。对于成年人来说,系统性的语音学习尤其重要,比如英语中的长元音、短元音、双元音和辅音。可以像我们学习汉语拼音一样,一个一个音去纠正发音。学习英语中,如果有条件,可以请外教帮助纠正发音。如果没有条件,自学的话,可以录下自己的发音,与标准发音对比。尤其需要注意的是,英语的每个音是如何发出的,是通过嘴唇、舌头、小舌、声带,还是鼻腔、口腔发音。在能够正确听出发音的基础上,去正确发音非常必要。
发音、朗读和对话练习是不可缺少的。成年人可以使用一些商务英语、生活英语等具体场景的对话材料来练习。不断地练习,并尝试用英语表达自己想说的话。从能正确听出并发出每个音素,到能正确拼读单词,再到读出单词重音,最后到整句整句地说话。随着语音语调的掌握,最终你会有表达能力上的提升。
听说是所有语言学习的基础,像建造高楼的地基,地基是否牢固直接影响之后的学习成果。学习听说时,初期可能没有语法教得那么正确,但这并不是大问题。初期的练习目标是肌肉记忆和听力训练,能够流利地说、正确地听。后期再结合语法知识,去纠正自己的表达。
我学英语时,老师常说,得单词者得天下。的确,拥有大量词汇且记忆力好的人在英语学习中会更受益。但需要注意的是,常用单词其实不多。如果你经历过九年义务教育、高中和大学,并能通过六级考试,那么按照我国的教学大纲,你的词汇量至少在 4000 多个。这 4000 多个词基本属于英语的常用词汇。根据《词行天下》的说法,英语的核心词汇不多,大约 250 词、3000 词、5000 词,分别对应不同频率的常用词。250 词主要是介词等“虚词”,属于相当重要的语法成分;3000 词和 5000 词则包括了常用的形容词、名词等,属于表义成分。但要进行交流需要 17000 词,考试则需要 20000 词左右,因为在英语语料库中不高频的词有时也是句子的关键成分。我想,你现在背单词的痛苦,可能也是因为这些。
我们在整个学生生涯中努力学习,毕业后“掌握”了 4000 多个词,但这些词我们真的掌握了吗?我们可能是通过拼读和死记硬背记住了单词,比如:“cat,c-a-t,cat,猫。”但由于日常没有英语场景,这些单词时间一长就还给老师了。关于单词学习,漏屋老师的方法总结为一句话:高频词多义多变形,注重发音,不能死记硬背,低频词适合记忆,并在使用中强化记忆。更详细的内容,可以阅读《词行天下》和《词霸天下》。
我个人建议通过阅读来提升词汇量。现在有一种词汇掌握量的评估标准叫蓝思值,你可以先测试自己的蓝思值,选择符合蓝思值的分级读物,逐步通过阅读练习来提升词汇量。这一类书的核心在于,书中的高频词是你现阶段可以掌握的词汇,阅读难度适合且情节有趣。
书面英语和口语英语的高频词差别很大,学术类英语又是另一块领域。你可以根据自己的目标选择词汇方向,选择自己有兴趣的领域去积累。你也可以通过英语场景去强化某个领域的词汇,比如旅游、看电影、谈恋爱、商务英语、儿童英语等。找个好玩的目标,也许能帮你轻松记住更多单词。像牛津高阶这样的学习词典,也会使用 OPAL 会把学术词汇分为口语词汇,写作词汇等。
语法当然重要,但并不是全部。在日常交流中,你可能表达得不够规范,语法也可能不完全正确,但对方依然能理解你的意思。然而,长期这样下去可能会影响你的语言思维和能力发展。对于语法学习,我建议首先忘记一切以前学过的语法知识,不要按照传统的名词、介词、副词等顺序去学了。
语法的学习,归根结底还是要回到它的起源,语言是活的,本身就没有一个严密的规律。所谓的语法,更多的是对常见且广为接受的共同表达习惯,尤其是文学作品等内容的规则话总结。比如,我问你,汉语有几种词?名、动、形、数、量、代、副、介、连、助、叹、拟声,你能答出来几个。实际上,你不知道这些语法知识并不影响你说汉语,甚至汉语的顺序并不影响阅读。
汉语如此,是因为我们作为汉语的使用者,通过阅读、通过听说、知道该去如何表达,这也是母语使用者先天的优势,但这并不是一蹴而就的。按照前面的《二语习得论》,幼儿在经过语言沉默期(纯听为主)后,进入的就是语法干扰期,通过犯错和纠错来慢慢形成第二语言的表达能力,并在学术提高期里面进行更高级的表达和纠错。
语法就是在学术提高期里帮助你提高语言使用的准确性和规范性的工具,同时帮助你更好地理解复杂句子结构的工具。很多人在初期被复杂的语法规则压得喘不过气来,实际上,不需要一开始就精通所有的语法规则。语言的学习是一个循序渐进的过程,先从简单的时态、句子结构开始,逐步再去学习更复杂的语法现象。
另外,语言是一种使用工具,而非知识考核。如果在交流时你过分拘泥于语法正确性,反而可能会妨碍你自然流利地表达。建议你在学习语法的同时,多听、多说,多通过语境来理解语法的使用,而不是仅仅背诵规则。
所以,可以从一些简单的句子结构开始,比如:主语 + 谓语 + 宾语(I love you.),然后慢慢加入一些修饰成分,比如定语和状语。通过多看、多听英语句子的实际使用,逐步加深对语法的理解。
可以尝试将一些日常的场景或对话进行简单的英语描述,并结合一些基础的语法书籍,帮助你理解常见语法点,如《剑桥初级英语语法》(Essential Grammar in use)。书中的例句通常比较简单易懂,同时也会提供一些练习题帮助你加深理解。
以上几点是我结合自己的实际经验,对你的来信的一些建议。须知纸上得来终觉浅,绝知此事要躬行。英语学习的理论只是起点,找到适合自己的学习方法才最重要。我建议你多多尝试,找到最适合自己的学习路径。
祝你英语学习顺利,取得进步。