2017-03-25 9 views
0

いくつかのmysqlクエリでいくつかの問題が発生していますが、何回か実行するのに約50秒かかりますが、もう1回は約1秒かかります。クエリは私が必要とすることをしますが、明らかに遅すぎます。以下 PHP/mysqlクエリのスピードアップ/ジョインの正しい使い方?

が使用され、3つのテーブルである列の一部を示す:

製品表(14315行)

id | title | image | price | rrp | upsell 
20381 | test | test | 24.00 | 30.00 | 1 

product_to_category表(26283行)

ptc_id | product_id | category_id 
33797 | 20381  | 29 

category_description表(29行)

category_id | name  | url_slug 
29   | Kitchens | kitchen-products 

seo_slugs表(14898行)以下

seo_slug_id | route   | seo_slug 
26987  | product=20381 | test-product-kitchen-area-2000-500 

私が使用しています現在のCodeIgniterの機能です。

public function getUpsells() { 
$this->db->select('products.id, products.title, products.image, products.category, products.price, products.rrp', FALSE); 
$this->db->from('product_to_category'); 
$this->db->join('products', 'products.id = product_to_category.product_id'); 
$this->db->join('category_description', 'category_description.category_id = product_to_category.category_id'); 
$this->db->join('seo_slugs', 'seo_slugs.route = concat(\'product=\', product_to_category.product_id)'); 
$this->db->where('products.upsell',1); 
$this->db->where('products.status',1); 
$this->db->group_by('product_to_category.product_id'); 
$query = $this->db->get(); 
return $query->result(); 

} 私は、誰かが私が間違っているつもりだ右方向やアドバイスに私を指すことができます願っています。私がクエリで結合を初めて使用したのは正直なところですが、動作しているように見えますが、最初にページを読み込むと非常に遅くなり、リフレッシュされた場合はかなり高速に読み込まれるようです。以下は

それが実行されるクエリです:

SELECT products.id, products.title, products.image, products.category, products.price, products.rrp 
FROM `product_to_category` 
JOIN `products` ON `products`.`id` = `product_to_category`.`product_id` 
JOIN `category_description` ON `category_description`.`category_id` = `product_to_category`.`category_id` 
JOIN `seo_slugs` ON `seo_slugs`.`route` = concat('product=', product_to_category.product_id) 
WHERE `products`.`upsell` = 1 
AND `products`.`status` = 1 
GROUP BY `product_to_category`.`product_id` 

を結果プロファイリング:

Starting 18 µs 
Waiting For Query Cache Lock 5 µs 
Checking Query Cache For Query 48 µs 
Checking Permissions 5 µs 
Checking Permissions 4 µs 
Checking Permissions 4 µs 
Checking Permissions 5 µs 
Opening Tables 20 µs 
System Lock 9 µs 
Waiting For Query Cache Lock 15 µs 
Init 25 µs 
Optimizing 13 µs 
Statistics 23 µs 
Preparing 19 µs 
Creating Tmp Table 21 µs 
Executing 5 µs 
Copying To Tmp Table 51.8 s 
Sorting Result 26 µs 
Sending Data 24 µs 
End 9 µs 
Removing Tmp Table 33 µs 
End 7 µs 
Query End 7 µs 
Closing Tables 14 µs 
Freeing Items 12 µs 
Waiting For Query Cache Lock 6 µs 
Freeing Items 11 µs 
Waiting For Query Cache Lock 7 µs 
Freeing Items 7 µs 
Storing Result In Query Cache 162 µs 
Logging Slow Query 6 µs 
Logging Slow Query 38 µs 
Cleaning Up 7 µs 

を検索結果をEXPLAIN:

+----+-------------+----------------------+--------+---------------+---------+---------+-----------------------------------------------------+-------+---------------------------------+ 
| id | select_type |  table   | type | possible_keys | key | key_len |       ref       | rows |    Extra    | 
+----+-------------+----------------------+--------+---------------+---------+---------+-----------------------------------------------------+-------+---------------------------------+ 
| 1 | SIMPLE  | seo_slugs   | ALL | NULL   | NULL | NULL | NULL            | 14958 | Using temporary; Using filesort | 
| 1 | SIMPLE  | product_to_category | ALL | category_id | NULL | NULL | NULL            | 26343 | Using where; Using join buffer | 
| 1 | SIMPLE  | category_description | eq_ref | PRIMARY  | PRIMARY | 4  | wilsonar_hcsupplies.product_to_category.category_id |  1 | Using index      | 
| 1 | SIMPLE  | products    | eq_ref | PRIMARY,id | PRIMARY | 4  | wilsonar_hcsupplies.product_to_category.product_id |  1 | Using where      | 
+----+-------------+----------------------+--------+---------------+---------+---------+-----------------------------------------------------+-------+---------------------------------+ 
+1

質問を編集し、*修飾*列名でクエリを表示してください。私たちはあなたのデータを今は持っていないので、列がどこからコーミングされているのかわかりません。 –

+0

インデックスが設定されていますか?ビューの使用はどうですか?一つのことは確かです:コンカットの使用は通常非常に遅いです。 – Jeff

+1

あなたのクエリのEXPLAINを表示 –

答えて

0

はEXPLAIN product_to_categoryは、MySQLが使用して考えていることをインデックスを持っていることを教えてくれるpossible_keysは "category_id"であるためです。ただし、何らかの理由で使用されていません。

"rows"は26343で、 "key"はNULLです。つまり、製品ごとにproduct_to_category内のすべての 26343行をスキャンする必要があります。これは、ジョインバッファの最適化を使用しても恐ろしいことになります。このテーブルの主キーは(PRODUCT_ID、CATEGORY_ID)にUNIQUEインデックスを持つ(CATEGORY_ID、PRODUCT_ID)である検索を最適化するために添加しなければならないので

product_to_category Table (26283 rows) 
ptc_id | product_id | category_id 
33797 | 20381  | 29 

ptc_idは、無駄です。これにより、データベース構造が疑わしいものになります。そのため、デザイナーがテーブルの列の1つに間違ったタイプ(つまり、INT以外のもの)を使用したことを賭けます。したがって、tinyint、smallint、bigint、unsignedなどのカラムタイプを確認してください。

他の原因は、category_idという名前のインデックスが実際にcategory_idカラムにインデックスを作成しないことです。あなたは、決して知らない。チェックしてください。

今や、クエリには別の問題があります。つまり、GROUP BYはクエリ全体を役に立たなくします。私はこのクエリが何をすることになっているのだろう...

0

(私はまだ有用な "プロファイル"を見ている。)

product_to_categoryのテーブル構造を見なくても、不足している部分だと思われます。多くのマッピングテーブル:ptc_id

  • 変更
  • PRIMARY KEY(product_id, category_id)にも最適な、多くのINDEX(category_id, product_id)
  • Further discussionを持っている場合

    • を取り除きます。

      また、INDEX(upsell, status)があります。この複合インデックスは、これらの列のカーディナリティに応じて使用される場合と使用されない場合があります。有用であれば、それは非常に有益です。そうでなければ、テーブルスキャンが必要です。

      最後の2つのjoin()を取り除きます。これらのテーブルは使用しません。 MySQLはそれらが存在することを確認するために参加していますが、そうする際に時間を無駄にします。

      2つの不要なテーブルを削除すると、GROUP BYを取り除くことができます。

      しかし、なぜcategoriesに触れるのですか?それを取り除くと、products_to_categoriesが取り除かれます。

      は、これはあなたが必要なすべてが上記の指標である、プラス

      SELECT id, title, image, category, price, rrp 
      FROM `products` 
      WHERE `upsell` = 1 
          AND `status` = 1 
      

      しかし、待って! products.categoryが存在しないため、これは機能しません。

      なぜ時々高速ですか? 「クエリキャッシュ」が有効になっています。 と同じクエリを再度実行すると、のいずれかのに変更されます。関連するテーブルはになります。これは通常、ミリ秒単位でQCからフェッチされます。