3

1 つの e コマース サイトを強化する itemsという名前の innodb テーブルがあります。検索システムを使用すると、オプション/追加フィールドを検索できるため、たとえば、修理されたコンピューターのみを検索したり、2000 年より古い車のみを検索したりできます。

これは、items_fieldsという追加のテーブルを介して行われます。非常にシンプルなデザインです。

+------------+------------------------+------+-----+---------+----------------+
| id         | int(11)                | NO   | PRI | NULL    | auto_increment |
| field_id   | int(11)                | NO   | MUL | NULL    |                |
| item_id    | int(11)                | NO   | MUL | NULL    |                |
| valueText  | varchar(500)           | YES  |     | NULL    |                |
| valueInt   | decimal(10,1) unsigned | YES  |     | NULL    |                |
+------------+------------------------+------+-----+---------+----------------+

フィールド名とタイプのみを含むフィールドと呼ばれるテーブルもあります。

検索結果を返す主なクエリは次のとおりです。

SELECT items...   
FROM items   
WHERE items... AND (  
      SELECT count(id)  
      FROM items_fields    
      WHERE items_fields.field_id = "59" AND items_fields.item_id = items.id AND
      items_fields.valueText = "Damaged")>0  
ORDER by ordering desc LIMIT 35;

大規模 (1 日あたり 400 万以上の検索クエリのみ) では、これらの高度な検索をさらに最適化する必要があります。現在、平均的な高度な検索クエリには約 100 ミリ秒かかります。

このクエリを高速化するにはどうすればよいですか? 他に最適化のための提案やアドバイスはありますか? 両方のテーブルはinnodbで、サーバースタックは絶対に素晴らしいですが、それでもこのクエリを解決する必要があります:)

4

1 に答える 1

0

これはあなたの検索であるため、(item_id, field_id, valueText) を追加してインデックスを付けます。

内側の選択を取り除きます!!! MySQL 5.5 までは、内部選択を使用してクエリを最適化できません。私の知る限り、MariaDB 5.5 は、現在内部選択の最適化をサポートしている唯一の MySQL 代替品です。

 SELECT i.*, f2.* as damageCounter FROM items i  
    JOIN items_fields f ON f.field_id = 59
                       AND f.item_id = i.id
                       AND f.valueText = "Damaged"
   JOIN item_fields f2 ON f2.item_id = i.id
   ORDER by i.ordering desc 

   LIMIT 35;

最初の結合では、返されるセットが制限されます。2 番目の結合は、最初の結合を満たすアイテムのすべての item_fields を取得します。最初と最後の結合の間に、追加のポイントに基づいて結果を除外する結合条件をさらに追加できます。例えば:

   SELECT i.*, f3.* as damageCounter FROM items i  
    JOIN items_fields f ON f.field_id = 59
                       AND f.item_id = i.id
                       AND f.valueText = "Damaged"
   JOIN items_fields f2 ON f2.field_id = 22
                       AND f2.item_id = i.id
                       AND f.valueText = "Green"
   JOIN item_fields f3 ON f3.item_id = i.id
   ORDER by i.ordering desc 

   LIMIT 35;

これは、フィールド 59 の値が「Damaged」で、フィールド 22 の値が「Green」であるすべてのアイテムの結果セットと、すべての item_fields を返します。

于 2012-11-13T13:22:38.877 に答える