0

ユーザーが自由形式のテキストボックスで検索を実行した後、(eコマースサイトで)製品を返すために使用されるMySQLデータベースにクエリがあります。

最近まで、ユーザー検索は高速で実行されていました。ただし、過去数日間、検索は定期的に非常に遅くなります。これは、毎日約3〜4時間(1日を通してランダムに広がる)発生します。

サーバーに問題があると思っていました。しかし今、私は別のサーバーに移動しました、そして同じことがまだ起こります。

私が使用しているクエリは非常に非効率的であると思われます。おそらくこれが原因です。しかし、なぜ通常はクエリが高速に実行され、他の場合には非常に低速になるのか理解できません。非効率的なクエリは常に遅いと思います。

クエリは2つのテーブルで実行されます。「ブルージーンズ」を検索すると、クエリは次のようになります。

SELECT I.itemURL, I.itemTitle, I.itemPrice, I.itemReduced, I.itemFileName, I.itemBrand, I.itemStore, I.itemID, I.itemColour, I.itemSizes, I.itemBrandEn
FROM Item AS I, Search AS S
    WHERE I.itemID = S.itemID
        AND (S.searchStringTEXT LIKE '% blue %' OR S.searchStringTEXT LIKE 'blue %' OR S.searchStringTEXT LIKE '% blue')
            AND (S.searchStringTEXT LIKE '% jeans %' OR S.searchStringTEXT LIKE 'jeans %' OR S.searchStringTEXT LIKE '% jeans')

アイテムは、サイト上のすべての製品を含むテーブルです。約100,000行あります。

検索は、製品IDと、各製品IDに関連付けられたタグを含むテーブルです。タグは「searchStringTEXT」列にあり、スペースで区切られています。たとえば、この列のエントリは「ジーンズブルーカルバンクラインスモール」のようなものです。

上記の検索では、「ジーンズ」と「青」の両方のタグが付いているすべてのアイテムが見つかります。

理論的には、検索にはアイテムと同じ行数が必要です。ただし、まだ修正していない問題のため、行数が約500少ないため、これらの項目は事実上検索から除外されます。

両方のテーブルのテーブル作成の詳細は次のとおりです。

CREATE TABLE `Search` (
  `itemID` int(11) NOT NULL,
  `searchStringTEXT` varchar(255) DEFAULT NULL,
  `searchStringVARCHAR` varchar(1000) DEFAULT NULL,
  PRIMARY KEY (`itemID`),
  KEY `indexSearch_837` (`itemID`) USING BTREE,
  KEY `indexSearch_837_text` (`searchStringTEXT`)
) ENGINE=InnoDB DEFAULT CHARSET=latin5

CREATE TABLE `Item_8372` (
  `itemID` int(11) NOT NULL AUTO_INCREMENT,
  `itemURL` varchar(2000) DEFAULT NULL,
  `itemTitle` varchar(500) DEFAULT NULL,
  `itemFileName` varchar(200) DEFAULT NULL,
  `itemPictureURL` varchar(2000) DEFAULT NULL,
  `itemReduced` int(11) DEFAULT NULL,
  `itemPrice` int(11) DEFAULT NULL,
  `itemStore` varchar(500) DEFAULT NULL,
  `itemBrand` varchar(500) CHARACTER SET latin1 DEFAULT NULL,
  `itemShopCat` varchar(500) DEFAULT NULL,
  `itemTimestamp` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `itemCat` varchar(200) DEFAULT NULL,
  `itemSubCat` varchar(200) DEFAULT NULL,
  `itemSubSubCat` varchar(200) DEFAULT NULL,
  `itemSubSubSubCat` varchar(200) DEFAULT NULL,
  `itemColour` varchar(200) DEFAULT NULL,
  `itemSizes` varchar(200) DEFAULT NULL,
  `itemBrandEn` varchar(500) DEFAULT NULL,
  `itemReduction` float DEFAULT NULL,
  `ItemPopularity` int(6) DEFAULT NULL,
  PRIMARY KEY (`itemID`),
  KEY `indexItem_8372_ts` (`itemTimestamp`) USING BTREE,
  KEY `indexItem_8372_pop` (`ItemPopularity`),
  KEY `indexItem_8372_red` (`itemReduction`),
  KEY `indexItem_8372_price` (`itemReduced`)
) ENGINE=InnoDB AUTO_INCREMENT=970846 DEFAULT CHARSET=latin5

質問のタイトルで「(私のWebサイトで実行した場合)」と言います。これは、ローカルで実行した場合にクエリの速度が一定であることがわかったためです。しかし、これは私がローカルであまりテストしていないからかもしれません。

SearchテーブルをMyISAMテーブルに変更することを考えています。そうすれば、「LIKE」の代わりに全文検索を使用できます。しかし、私はまだ、現在のセットアップで経験していることをなぜ経験しているのかを理解したいと思います。

アンドリュー、どんなアイデア/提案も大歓迎です

編集:

SELECTステートメントのEXPLAIN結果は次のとおりです。

id  select_type table   type    possible_keys   key key_len ref rows         Extra
1   SIMPLE  I   ALL PRIMARY NULL    NULL    NULL    81558   
1   SIMPLE  S   eq_ref  PRIMARY,indexSearch_837,indexSearch_837_text    PRIMARY 4       I.itemID    1   Using where
4

2 に答える 2

1

REGEXP(参照)を使用してみてください。また、暗黙的な結合の使用を停止することをお勧めします。

SELECT I.itemurl, 
       I.itemtitle, 
       I.itemprice, 
       I.itemreduced, 
       I.itemfilename, 
       I.itembrand, 
       I.itemstore, 
       I.itemid, 
       I.itemcolour, 
       I.itemsizes, 
       I.itembranden 
FROM   item AS I 
       INNER JOIN search AS S 
               ON I.itemid = S.itemid 
WHERE  S.searchstringtext REGEXP ' blue | blue|blue ' 
       AND S.searchstringtext REGEXP ' jeans | jeans|jeans ' 
于 2012-12-11T16:46:26.197 に答える
1

を使用LIKEすると、クエリが遅くなり、特にその回数が多くなります。これは、 がテーブル内のすべての行をスキャンするためです。これは、数百行であっても問題を引き起こす可能性があります (一致させるためにさまざまなバリエーションのテキストをLIKE使用した回数をそれに加えます)。LIKE

このクエリを実行するページを数人が同時にロードするだけで、サイトの速度が大幅に低下します。さらに、以前のバックグラウンド スレッドでサーバー上でクエリが複数回実行されている可能性があり、これが長期的な速度低下の原因となっています。

テキスト検索を定期的に実行する場合は、Sphinx などの検索用の RAM ベースのインデックス作成ソリューションを検討してください。そこでテキスト検索を実行し (MySQL に比べて非常に高速です)、必要な行を MySQL テーブルから取得できます。

于 2012-12-11T16:29:23.533 に答える