关键词匹配项目深入研究(二)- 分表思想的引入,关键词深入研究
关键词匹配项目深入研究(二)- 分表思想的引入,关键词深入研究
(二)分表思想的引入
近期的文章: 1)高并发数据采集的架构应用(Redis的应用)
2)高可用数据采集平台(如何玩转3门语言php+.net+aauto)
手把手教你做关键词匹配项目这块基本已经完成,深入研究是对系统的性能作为分析,在一些环境的刺激下所必需要做的一些改变。
手把手教你做关键词匹配项目: 手把手教你做关键词匹配项目(搜索引擎)---- 第一天~手把手教你做关键词匹配项目(搜索引擎)---- 第二十二天 (共22篇)
深入研究:上节讲到 关键词匹配项目深入研究-过滤器的引入。
每一篇会分为问题的前因、解决方案以及有些必要的实现方案。
本篇正文正式开始。
问题的前因
随着自动采集数据的爆炸式的增长,词库的容量蒸蒸日上,一下从几W数据猛增几百万数据,小帅帅看着数据库的查询越来越感到无能为力。
再加上小丁丁常对小帅帅说的最多的一句:何时那么选词能快一点,每次我都等好久都莫有反应,真是急死我了。
小帅帅也比较焦急,心力憔悴,真正的感觉到原来这就是挑战。小帅帅无可奈何的继续找到于老大,求于老大赏赐高招。
于老大拍拍小帅帅的肩膀:小伙子,知道项目的难度了吧!
小帅帅回答道:别挖苦我了,我已深深的感受到了,我想我心脏估计快承受不了了。
于老大:就这点你就承受不了,那估计以后有的是给你受的。
小帅帅:大哥,别说这些虚的行不,赶紧的解决方案丫。
于老大:急啥,事情是急不来的,过来,哥给你指条明路。
“每个宝贝是不是有类别的属性,那么这几百万数据真正属于这个类别的词能够有多少?假设我们只取这个类别的词库我们的项目是否可以继续稳定下来”。
解决方案
按照某种业务需要,我们可以对数据表实行分割,可以纵向或者横向分割,可以有效的进行性能优化。
纵向分割也称列分割,把不常用的列或者长字段分割来保证实体处于一个相对适用的状态,常见的有一对一关联。
横向分割也称行分割,按照某种业务拆分数据的记录来存放在不同的表,常见的有按日期分表操作。
本案例是使用横向分割,把数据按照类别的形式进行拆分。
实现方案
我们为了不更改数据表的结构,这样设计了,我们按照表名来区分项目使用那个数据表。这样一来的改动相对是非常少的。我们只需稍微改动下代码就可以解决了,这很心塞的一件事情。
修改Keyword的代码,增加获取数据源。
<?<span>php </span><span>define</span>('DATABASE_HOST','127.0.0.1'<span>); </span><span>define</span>('DATABASE_USER','xiaoshuaishuai'<span>); </span><span>define</span>('DATABASE__PASSWORD','xiaoshuaishuai'<span>); </span><span>define</span>('DATABASE_CHARSET','utf-8'<span>); </span><span>class</span><span> Keyword { </span><span>public</span> <span>$word</span><span>; </span><span>public</span> <span>static</span> <span>$conn</span> = <span>null</span><span>; </span><span>public</span> <span>function</span><span> getDbConn(){ </span><span>if</span>(self::<span>$conn</span> == <span>null</span><span>){ self</span>::<span>$conn</span> = <span>mysql_connect</span>(DATABASE_HOST,DATABASE_USER,<span>DATABASE__PASSWORD); </span><span>mysql_query</span>("SET NAMES '".DATABASE_CHARSET."'",self::<span>$conn</span><span>); </span><span>mysql_select_db</span>("dict",self::<span>$conn</span><span>); </span><span>return</span> self::<span>$conn</span><span>; } </span><span>return</span> self::<span>$conn</span><span>; } </span><span>public</span> <span>function</span><span> save(){ </span><span>$sql</span> = "insert into keywords(word) values ('<span>$this</span>->word')"<span>; </span><span>return</span> <span>mysql_query</span>(<span>$sql</span>,<span>$this</span>-><span>getDbConn()); } </span><span>public</span> <span>static</span> <span>function</span> getWordsSource(<span>$cid</span>,<span>$limit</span>=0,<span>$offset</span>=40<span>){ </span><span>$sql</span> = "SELECT * FROM keywords_<span>$cid</span> LIMIT <span>$limit</span>,<span>$ffset</span>"<span>; </span><span>return</span> DB::MakeArray(<span>$sql</span><span>); } </span><span>public</span> <span>static</span> <span>function</span> getWordsCount(<span>$cid</span><span>){ </span><span>$sql</span> = "SELECT count(*) FROM keywords_<span>$cid</span>"<span>; </span><span>return</span> DB::QueryScalar(<span>$sql</span><span>); } }</span>
DB类新增QueryScalar,用于算总量
<?<span>php </span><span>#</span><span>@author oShine</span> <span>define</span>('DATABASE_HOST','127.0.0.1'<span>); </span><span>define</span>('DATABASE_USER','xiaoshuaishuai'<span>); </span><span>define</span>('DATABASE__PASSWORD','xiaoshuaishuai'<span>); </span><span>define</span>('DATABASE_CHARSET','utf-8'<span>); </span><span>class</span><span> DB { </span><span>public</span> <span>static</span> <span>$conn</span> = <span>null</span><span>; </span><span>public</span> <span>static</span> <span>function</span><span> Connect(){ </span><span>if</span>(self::<span>$conn</span> == <span>null</span><span>){ self</span>::<span>$conn</span> = <span>mysql_connect</span>(DATABASE_HOST,DATABASE_USER,<span>DATABASE__PASSWORD); </span><span>mysql_query</span>("SET NAMES '".DATABASE_CHARSET."'",self::<span>$conn</span><span>); </span><span>mysql_select_db</span>("dict",self::<span>$conn</span><span>); </span><span>return</span> self::<span>$conn</span><span>; } </span><span>return</span> self::<span>$conn</span><span>; } </span><span>public</span> <span>static</span> <span>function</span> Query(<span>$sql</span><span>){ </span><span>return</span> <span>mysql_query</span>(<span>$sql</span>,self::<span>Connect()); } </span><span>public</span> <span>static</span> <span>function</span> makeArray(<span>$sql</span><span>){ </span><span>$rs</span> = self::Query(<span>$sql</span><span>); </span><span>$result</span> = <span>array</span><span>(); </span><span>while</span>(<span>$data</span> = <span>mysql_fetch_assoc</span>(<span>$rs</span><span>)){ </span><span>$result</span>[] = <span>$data</span><span>; } </span><span>return</span> <span>$result</span><span>; } </span><span>public</span> <span>static</span> <span>function</span> QueryScalar(<span>$sql</span><span>){ </span><span>$rs</span> = self::Query(<span>$sql</span><span>); </span><span>$data</span> = <span>mysql_fetch_array</span>(<span>$rs</span><span>); </span><span>if</span>(<span>$data</span> == <span>false</span> || <span>empty</span>(<span>$data</span>) || !<span>isset</span>(<span>$data</span>[1])) <span>return</span> 0<span>; </span><span>return</span> <span>$data</span>[1<span>]; } } </span>
修改Selector的代码,用于选词:
<?<span>php </span><span>#</span><span>@Filename:selector/Selector.php</span><span> #</span><span>@Author:oshine</span> <span>require_once</span> <span>dirname</span>(<span>__FILE__</span>) . '/SelectorItem.php'<span>; </span><span>require_once</span> <span>dirname</span>(<span>__FILE__</span>) . '/charlist/CharList.php'<span>; </span><span>require_once</span> <span>dirname</span>(<span>__FILE__</span>) . '/charlist/CharlistHandle.php'<span>; </span><span>require_once</span> <span>dirname</span>(<span>dirname</span>(<span>__FILE__</span>)) . '/lib/Logger.php'<span>; </span><span>class</span><span> Selector { </span><span>private</span> <span>static</span> <span>$charListHandle</span> = <span>array</span><span>( </span>"黑名单" => "BacklistCharListHandle", "近义词" => "LinklistCharListHandle"<span> ); </span><span>public</span> <span>static</span> <span>function</span> select(<span>$num_iid</span><span>) { </span><span>$selectorItem</span> = SelectorItem::createFromApi(<span>$num_iid</span><span>); Logger</span>::trace(<span>$selectorItem</span>-><span>props_name); </span><span>$charlist</span> = <span>new</span><span> CharList(); </span><span>foreach</span> (self::<span>$charListHandle</span> <span>as</span> <span>$matchKey</span> => <span>$className</span><span>) { </span><span>$handle</span> = self::createCharListHandle(<span>$className</span>, <span>$charlist</span>, <span>$selectorItem</span><span>); </span><span>$handle</span>-><span>exec</span><span>(); } </span><span>$selectWords</span> = <span>array</span><span>(); </span><span>$wordsCount</span> = Keyword::getWordsCount(selectorItem-><span>cid); </span><span>$offset</span> = 40<span>; </span><span>$page</span> = <span>ceil</span>(<span>$wordsCount</span>/<span>$offset</span><span>); </span><span>for</span>(<span>$i</span>=0;<span>$i</span><=<span>$page</span>;<span>$i</span>++<span>){ </span><span>$limit</span> = <span>$i</span>*<span>$offset</span><span>; </span><span>$keywords</span> = Keyword::getWordsSource(selectorItem->cid,<span>$limit</span>,<span>$offset</span><span>); </span><span>foreach</span> (<span>$keywords</span> <span>as</span> <span>$val</span><span>) { </span><span>#</span><span> code...</span> <span>$keywordEntity</span> = SplitterApp::<span>split</span>(<span>$val</span>["word"<span>]); </span><span>#</span><span> code...</span> <span>if</span>(MacthExector::macth(<span>$keywordEntity</span>,<span>$charlist</span><span>)){ </span><span>$selectWords</span>[] = <span>$val</span>["word"<span>]; } } } </span><span>return</span> <span>$selectWords</span><span>; } </span><span>public</span> <span>static</span> <span>function</span> createCharListHandle(<span>$className</span>, <span>$charlist</span>, <span>$selectorItem</span><span>) { </span><span>if</span> (<span>class_exists</span>(<span>$className</span><span>)) { </span><span>return</span> <span>new</span> <span>$className</span>(<span>$charlist</span>, <span>$selectorItem</span><span>); } </span><span>throw</span> <span>new</span> <span>Exception</span>("class not exists", 0<span>); } }</span>
总结
小帅帅又学到了新的知识点,这是要犒劳于老大的节奏吗?你们是否也要犒劳下我呢,求赞哈!

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











印刷が必要なファイルを開いたときに、印刷プレビューで表の枠線が何らかの原因で消えてしまった場合は、早めに対処する必要があります。 file このような質問がある場合は、エディターに参加して次のコースを学習してください: Excel で表を印刷するときに枠線が消えた場合はどうすればよいですか? 1. 次の図に示すように、印刷する必要があるファイルを開きます。 2. 以下の図に示すように、必要なコンテンツ領域をすべて選択します。 3. 以下の図に示すように、マウスを右クリックして「セルの書式設定」オプションを選択します。 4. 以下の図に示すように、ウィンドウの上部にある「境界線」オプションをクリックします。 5. 下図に示すように、左側の線種で細い実線パターンを選択します。 6.「外枠」を選択します

Excelは日々の事務作業でデータ処理に使用されることが多く、「フィルター」機能を使用することが多いです。 Excel で「フィルタリング」を実行する場合、同じ列に対して最大 2 つの条件しかフィルタリングできません。では、Excel で同時に 3 つ以上のキーワードをフィルタリングする方法をご存知ですか?次に、それをデモンストレーションしてみましょう。 1 つ目の方法は、フィルターに条件を徐々に追加することです。条件を満たす 3 つの詳細を同時にフィルターで除外する場合は、まずそのうちの 1 つを段階的にフィルターで除外する必要があります。最初に、条件に基づいて姓が「Wang」の従業員をフィルタリングできます。 [OK]をクリックし、フィルター結果の[現在の選択をフィルターに追加]にチェックを入れます。手順は以下の通りです。同様に再度個別にフィルタリングを行う

私たちは日々の仕事や勉強で、他人からExcelファイルをコピーし、そのファイルを開いて内容を追加したり、再編集したりして保存することがありますが、互換性チェックのダイアログボックスが表示されることがあり、非常に面倒です。ソフトウェア. 、通常モードに変更できますか?そこで以下では、エディターがこの問題を解決するための詳細な手順を紹介します。一緒に学びましょう。最後に、忘れずに保存してください。 1. 図に示すように、ワークシートを開き、ワークシートの名前に追加の互換モードを表示します。 2. このワークシートでは、内容を変更して保存すると、図のように互換性チェックのダイアログが必ず表示され、非常に面倒です。 3. [Office] ボタンをクリックし、[名前を付けて保存] をクリックして、

データを処理していると、倍数や温度などのさまざまな記号が含まれるデータに遭遇することがあります。 Excel で上付き文字を設定する方法をご存知ですか? Excel を使用してデータを処理する場合、上付き文字を設定しないと、大量のデータを入力するのがさらに面倒になります。今回はエクセルの上付き文字の具体的な設定方法をエディターがお届けします。 1. まず、図に示すように、デスクトップで Microsoft Office Excel ドキュメントを開き、上付き文字に変更する必要があるテキストを選択します。 2. 次に、図に示すように、右クリックして、クリック後に表示されるメニューで「セルの書式設定」オプションを選択します。 3. 次に、自動的に表示される「セルの書式設定」ダイアログボックスで

ほとんどのユーザーは Excel を使用してテーブル データを処理します。実は Excel にも VBA プログラムがあります。専門家を除けば、この関数を使用したユーザーはあまり多くありません。VBA で記述するときによく使用されるのが iif 関数です。実際には、次の場合と同じです。関数の機能は似ていますが、iif関数の使い方を紹介します。 SQL ステートメントには iif 関数があり、Excel には VBA コードがあります。 iif 関数は Excel ワークシートの IF 関数と似ており、論理的に計算された真値と偽値に基づいて真偽値を判定し、異なる結果を返します。 IF 関数の使用法は (条件、はい、いいえ) です。 VBAのIF文とIIF関数、前者のIF文は条件に応じて異なる文を実行できる制御文であり、後者は条件に応じて異なる文を実行できる制御文です。

e私たちはExcelを使ってデータテーブルなどを作成することがあります。パラメータ値を入力するときに、特定の数値の上付きまたは下付きが必要になることがあります。たとえば、数式がよく使用されます。では、Excelで下付き文字を入力するにはどうすればよいですか?詳細な手順を見てください: 1. 上付き文字の方法: 1. まず、Excel に a3 (3 は上付き文字) と入力します。 2. 数字「3」を選択し、右クリックして「セルの書式設定」を選択します。 3. 「上付き文字」をクリックし、「OK」をクリックします。 4. ほら、効果はこんな感じです。 2. 下付き文字の設定方法: 1. 上付き文字の設定方法と同様に、セルに「ln310」(3 は下付き文字) と入力し、数字の「3」を選択し、右クリックして「セルの書式設定」を選択します。 2.「下付き文字」にチェックを入れて「OK」をクリックします。

ソフトウェアの学習では、Excel が便利なだけでなく、実際の作業で必要なさまざまな形式に対応できるため、Excel の使用に慣れています。Excel は非常に柔軟に使用でき、今日は「みんなのために:Excelの読み取りモードを設定する場所」を持ってきました。 1. コンピュータの電源を入れ、Excel アプリケーションを開き、目的のデータを見つけます。 2. Excel で読み取りモードを設定するには 2 つの方法があります。 1 つ目: Excel には、Excel レイアウトで多数の便利な処理メソッドが配布されています。 Excelの右下に読み取りモードを設定するショートカットがあります。バツマークのパターンを見つけてクリックすると、読み取りモードに入ります。バツマークの右側に小さな立体マークがあります。 。

1. PPT を開き、Excel アイコンを挿入する必要があるページに移動します。 「挿入」タブをクリックします。 2. [オブジェクト]をクリックします。 3. 次のダイアログボックスが表示されます。 4. [ファイルから作成]をクリックし、[参照]をクリックします。 5. 挿入する Excel テーブルを選択します。 6. [OK] をクリックすると、次のページが表示されます。 7. [アイコンで表示]にチェックを入れます。 8. 「OK」をクリックします。
