20

私は会社のイントラネット用にかなり大きな「検索」エンジンを構築しています。1miljonに加えて、かなり高速なサーバーで実行されているエントリがありますが、一部の検索クエリには最大1分かかります。

これがテーブルの外観です

テーブル

インデックスを作成してみましたが、何か足りないようです。これがshowindexの表示です。

idexes

これはクエリ自体であり、クエリをほとんど遅くするのは順序ですが、並べ替えのないクエリでも多少遅くなります。

SELECT SQL_CALC_FOUND_ROWS *
FROM `businessunit`
INNER JOIN `businessunit-postaddress` ON `businessunit`.`Id` = `businessunit-postaddress`.`BusinessUnit`
WHERE `businessunit`.`Name` LIKE 'tanto%'
ORDER BY `businessunit`.`Premium` DESC ,
CASE WHEN `businessunit`.`Name` = 'tanto'
THEN 0
WHEN `businessunit`.`Name` LIKE 'tanto %'
THEN 1
WHEN `businessunit`.`Name` LIKE 'tanto%'
THEN 2
ELSE 3
END , `businessunit`.`Name`
LIMIT 0 , 30

どんな助けでも大歓迎です

編集: このクエリを99%窒息させているのは、ワイルドキャラクターとの関連性による順序付け% です。fsortを使用する

4

10 に答える 10

19

全文検索エンジンであるスフィンクス検索ソリューションを試してみてください。関連性を設定するための多くのオプションとともに、非常に優れたパフォーマンスが得られます。

詳細については、ここをクリックしてください。

于 2013-01-28T11:52:51.007 に答える
6

インデックスがカバーしていないようPremiumですが、それが最初のORDER BY引数です。

http://dev.mysql.com/doc/refman/5.0/en/using-explain.htmlEXPLAIN your query hereで説明されているように、クエリプランを把握し、インデックスを変更してテーブルスキャンを削除するために使用します

于 2013-01-28T11:52:07.060 に答える
6

MySQLはデータの保存には適していますが、高速テキストベースの検索に関してはあまり適していません。

すでに提案されているSphinxとは別に、2つの素晴らしい検索エンジンをお勧めします。

  1. http://pecl.php.net/package/solrを使用したSolr-非常に人気のある検索エンジン。NetFlixのような大規模なサービスで使用されます。

  2. Elastic Search-比較的新しいソフトウェアですが、非常に活発なコミュニティと多くの敬意を持っています

どちらのソリューションも同じライブラリApacheLuceneに基づいています

于 2013-02-07T15:41:36.410 に答える
2

検索エンジン向けのサイトのほとんどは使用されていますFULL-TEXT-SEARCH。と比較して非常に高速にselectなりLIKEます...1つの例といくつかのリンクを追加しました...それはあなたにとって役立つと思います...この全文検索にはいくつかの条件もあります...

ステップ1

CREATE TABLE articles (
    id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
    title VARCHAR(200),
    body TEXT,
    FULLTEXT (title,body)
);

ステップ2

INSERT INTO articles (title,body) VALUES
    ('MySQL Tutorial','DBMS stands for DataBase ...'),
    ('How To Use MySQL Well','After you went through a ...'),
    ('Optimizing MySQL','In this tutorial we will show ...'),
    ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
    ('MySQL vs. YourSQL','In the following database comparison ...'),
    ('MySQL Security','When configured properly, MySQL ...');

ステップ:3
自然言語全文検索:

SELECT * FROM articles
    WHERE MATCH (title,body) AGAINST ('database');

ブール全文検索

SELECT * FROM articles WHERE MATCH (title,body)
     AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);

このリンクを たどるviruspatel.netdevzone.zend.comsqlmag.comcolorado.eduen.wikipedia.org

于 2013-02-04T07:35:20.850 に答える
2

「ORDERBY」が本当にボトルネックである場合、簡単な解決策は、クエリから「ORDER BY」ロジックを削除し、C#並べ替えを使用してアプリケーションのコードに直接並べ替えを再実装することです。残念ながら、これは、ページ付けをアプリケーションに移動する必要があることを意味します。これは、並べ替えとページ付けを行う前に、完全な結果セットを取得する必要があるためです。これまで誰も考えていなかったように見えるので、私はこれについて言及しているだけです。

率直に言って(他の人が指摘しているように)、上部に表示したクエリはフルテキストインデックスを必要としないはずです。問題の列でBTREE(HASHではなく)インデックスが使用可能である限り、単一のサフィックスワイルドカード(たとえば、LIKE'ABC%')は非常に効果的です。

そして、個人的には、ダブルワイルドカード(たとえば、LIKE'%ABC% ")でさえ嫌悪感はありません。もちろん、全表スキャンが安価である限り、インデックスを使用することはできません。おそらく250,000行がポイントです。ここで、フルテキストインデックス作成を真剣に検討し始めます。100,000は間違いなく問題ありません。

ただし、SELECTがダーティリードであることを常に確認します(選択にトランザクション性は適用されません)。

とにかくユーザーの目に届くと汚れます!

于 2013-02-05T23:39:39.480 に答える
1

それはとても奇妙なクエリです:)それが何をするのか理解してみましょう。

結果は、いくつかの条件でテーブル「businessunit」から30行未満です。

最初の条件は、「businessunit-postaddress」テーブルの外部キーです。
列にインデックスがあるかどうかを確認してくださいbusinessunit-postaddressBusinessUnit

2つ目は、。のみで行を返すためのフィルターですbusinessunitName「タント」で始まります。
私が間違えなかった場合、あなたは非常に複雑なインデックスを持っています'ビジネス'は11のフィールドで構成されています!
また、フィールド'Name'は、このインデックスの最初のフィールドではありません。
したがって、「like tanto%」のクエリを実行する場合、このインデックスは役に立ちません。
この指標の必要性には全く疑問があります。
ちなみに、このテーブルを使用した編集操作の維持と速度低下には、非常に大きなリソースが必要です。
'Name'フィールドのみでインデックスを作成する必要があります。

クエリをフィルタリングした後、結果を並べ替えて、奇妙な方法でそれを実行します。
最初はフィールドでソートしますbusinessunitPremium-それは正常です。
ただし、CASEを使用した次のステートメントも役に立ちません。
それが理由です。
ゼロはName='tanto'(正確に)に割り当てられます。
次の1行は、「tanto」の後にスペースがある行です。これらは、どのような場合でも(特殊記号を除く)「tanto」の後になります。スペースがどの文字よりも低いためです。
2つの次の行は、「tanto」(スペースを含む)の後にいくつかの文字が含まれる行です。これらの行も、定義上、この順序になります。
そして、3つは「その他」の行用に「予約」されていますが、「その他」の行は取得されません。[WHERE businessunitNameお気に入り '
したがって、ORDERBYのこの部分は無意味です。
そして、ORDERBYの最後にがありbusinessunitます。Nameまた...

私のアドバイス:取得したいものを念頭に置いて、クエリを最初から再構築する必要があります。

とにかく私はあなたが使うことができると思います

SELECT SQL_CALC_FOUND_ROWS *
FROM `businessunit`
INNER JOIN `businessunit-postaddress` ON `businessunit`.`Id` = `businessunit-postaddress`.`BusinessUnit`
WHERE `businessunit`.`Name` LIKE 'tanto%'
ORDER BY `businessunit`.`Premium` DESC,
`businessunit`.`Name`
LIMIT 0 , 30

フィールドのインデックスを忘れないでくださいbusinessunit-postaddressBusinessUnit

そして、私はフィールドプレミアムについて強い仮定を持っています。バイナリデータを保存するために設計されていると思います(はい/いいえ)。したがって、通常の(BTREE)インデックスは一致しません。ビットマップインデックスを使用する必要があります。

PS本当にSQL_CALC_FOUND_ROWSMySQLを使用する必要があるかどうかわかりません :ページネーション-SQL_CALC_FOUND_ROWS vs COUNT()-クエリ

于 2013-02-09T11:51:39.243 に答える
1

フルテキスト(http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html)またはパターンマッチング(http://dev.mysql.com/doc/refman/5.0 ) /en/pattern-matching.html)phpおよびmysql側から。

経験と理論から:

フルテキストの利点
-1)結果は非常に関連性が高く、検索クエリの間隔などの文字を区切ることで検索が妨げられることはありません。
フルテキストのデメリット
-1)データの過剰な読み込みを防ぐためにウェブホスティング業者が制限として使用するストップワードがあります(たとえば、「one」または「moz」という単語を含む検索結果は表示されません。これは、次の場合に回避できます。 「ストップワードを保持せずに独自のサーバーを実行しています
。2)「ree」と入力すると、「ree」を含む単語のみが表示され、「three」や「reed」は表示されません。

パターンマッチングの利点
-1)フルテキストのようにストップワードがなく、「ree」を検索すると、正確な単語のみが含まれるフルテキストとは異なり、「reed」や「three」などの「ree」を含む単語が表示されます。取得されます。
パターンマッチングのデメリット
-1)検索ワードでスペースなどの区切り文字が使用されていて、これらのスペースが結果に含まれていない場合、各単語は区切り文字とは別であるため、結果は返されません。

于 2013-02-16T05:00:48.500 に答える
0

例のように、LIKEの引数がワイルドチャード文字で始まらない場合、LIKE演算子はインデックスを利用できるはずです。

この場合、LIKE演算子はLOCATEやLEFTよりもパフォーマンスが優れているはずなので、このように条件を変更すると状況が悪化する可能性がありますが、それでも試してみる価値はあると思います(誰が知っていますか?):

WHERE LOCATE('tanto', `businessunit`.`Name`)=1

また:

WHERE LEFT(`businessunit`.`Name`,5)='tanto'

また、条項ごとに注文を変更します。

ORDER BY
  `businessunit`.`Premium` DESC ,
   CASE WHEN `businessunit`.`Name` LIKE 'tanto %' THEN 1
        WHEN `businessunit`.`Name` = 'tanto'      THEN 0
        ELSE 2 END,
   `businessunit`.`Name`

名前はすでにLIKE'tanto%'である必要があるため、条件をスキップできます(CASEが値3を返すことはありません)。もちろん、Premiumフィールドにインデックスが付けられていることを確認してください。

お役に立てれば。

于 2013-02-04T11:25:54.050 に答える
0

キーだけを集めて並べ替えて、最後に参加する必要があると思います

SELECT A.*,B.* FROM
(
    SELECT * FROM (
        SELECT id BusinessUnit,Premium
            CASE
                WHEN Name = 'tanto'      THEN 0
                WHEN Name LIKE 'tanto %' THEN 1
                WHEN Name LIKE 'tanto%'  THEN 2
                ELSE 3
            END SortOrder
        FROM businessunit Name LIKE 'tanto%'
    ) AA ORDER BY Premium,SortOrder LIMIT 0,30
) A LEFT JOIN `businessunit-postaddress` B USING (BusinessUnit);

これでもファイルソートが生成されます。

インデックスを作成できる別のテーブルに必要なキーをプリロードすることを検討することをお勧めします。

CREATE TABLE BusinessKeys
(
    id int not null auto_increment,
    BusinessUnit int not null,
    Premium      int not null,
    SortOrder    int not null,
    PRIMARY KEY (id),
    KEY OrderIndex (Premuim,SortOrder,BusinessUnit)
);

一致するすべてのキーを入力します

INSERT INTO BusinessKeys (BusinessUnit,Premuim,SortOrder)
SELECT id,Premium
    CASE
        WHEN Name = 'tanto'      THEN 0
        WHEN Name LIKE 'tanto %' THEN 1
        WHEN Name LIKE 'tanto%'  THEN 2
        ELSE 3
    END
FROM businessunit Name LIKE 'tanto%';

次に、ページ付けするには、BusinessKeysでのみLIMITを実行します

SELECT A.*,B.*
FROM
    (
        SELECT FROM BusinessKeys
        ORDER BY Premium,SortOrder
        LIMIT 0,30
    ) BK
    LEFT JOIN businessunit A ON BK.BusinessUnit = A.id
    LEFT JOIN `businessunit-postaddress` B ON A.BusinessUnit = B.BusinessUnit
;

警告:クエリの左側からのキーの順序を保持するため、代わりLEFT JOINに使用します。INNER JOINLEFT JOIN

于 2013-02-07T06:08:57.617 に答える
0

Sphinxを使用して検索を最適化するための回答を読みました。しかし、私の経験に関しては、別の解決策をアドバイスしたいと思います。Sphinxを数年間使用しましたが、セグメンテーション違反と破損したインデックスに関するいくつかの厄介な問題がありました。おそらく、Sphinxは数年前ほどバグが少ないわけではありませんが、1年間、別の解決策に非常に満足しています。

http://www.elasticsearch.org/

大きなメリット:

  • スケーラビリティ-構成がほぼゼロの別のサーバーを追加するだけです。mysqlレプリケーションを知っている場合は、この機能を気に入るはずです
  • 速度-重い負荷がかかっていても、1秒もかからずに良い結果が得られます
  • 習得が容易-HTTPとJSONを知っているだけで使用できます。あなたがWeb開発者なら、あなたは家のように感じます
  • インストールが簡単-構成に触れることなく使用できます。パブリックからの直接アクセスをブロックするには、単純なJava(Tomcatなどは不要)とファイアウォールが必要です。
  • 優れたJavascript統合-phpMyAdminのようなツールでさえJavascriptを使用した単純なHTMLページです:https ://github.com/mobz/elasticsearch-head
  • https://github.com/ruflin/Elasticaとの良好なPHP統合
  • 良いコミュニティサポート
  • 優れたドキュメント(目に優しいわけではありませんが、ほぼすべての機能をカバーしています!)

追加のストレージソリューションが必要な場合は、検索エンジンをhttp://couchdb.apache.org/と簡単に組み合わせることができます。

于 2013-02-08T17:39:09.283 に答える