2017-11-02 14 views
0

Query-クエリの書式に書き換え

SELECT SUM(sale_data.total_sale) as totalsale, `sale_data_temp`.`customer_type_cy` as `customer_type`, `distributor_list`.`customer_status` FROM `distributor_list` LEFT JOIN `sale_data` ON `sale_data`.`depo_code` = `distributor_list`.`depo_code` and `sale_data`.`customer_code` = `distributor_list`.`customer_code` LEFT JOIN `sale_data_temp` ON `distributor_list`.`address_coordinates` = `sale_data_temp`.`address_coordinates` LEFT JOIN `item_master` ON `sale_data`.`item_code` = `item_master`.`item_code` WHERE `invoice_date` BETWEEN "2017-04-01" and "2017-11-01" AND `item_master`.`id_category` = 1 GROUP BY `distributor_list`.`address_coordinates` 

クエリを、インデックス化にもかかわらず、あまりにも多くの時間を割いて参加します。

SELECT SUM(sale_data.total_sale) as totalsale, 
     sale_data_temp.customer_type_cy as customer_type, 
     distributor_list.customer_status 
    FROM distributor_list 
    LEFT JOIN sale_data 
      ON sale_data.depo_code = distributor_list.depo_code 
      and sale_data.customer_code = distributor_list.customer_code 
    LEFT JOIN sale_data_temp 
      ON distributor_list.address_coordinates = sale_data_temp.address_coordinates 
    LEFT JOIN item_master 
      ON sale_data.item_code = item_master.item_code 
WHERE invoice_date BETWEEN "2017-04-01" and "2017-11-01" 
    AND item_master.id_category = 1 
GROUP BY distributor_list.address_coordinates 

DESC- このクエリはrun.Myアプリケーションに7.5秒を取って3-4等queries.Thereforeのロード時間がサーバー上で1分をappraches含まれています。
私の販売データテーブルには4.5 lakh(450K)のレコードが含まれています。
配布リストには970件のレコードが含まれています。
アイテムマスタには7774個のレコードが含まれ、sale_data_tempには324個のレコードが含まれます。
私はインデックスを使用していますが、販売データテーブルには使用されていません。
Explain SQLから明らかなように、すべての4 lakh(400K)レコードが検索されます。
私はBETWEEN節の期​​間を減らす場合、販売データテーブルは日付インデックスを使用します。それ以外の場合は、4 lakh行すべてをスキャンします。
01-04-2017と01-11-2017の間の行は84000ですが、それでも4ラフの行をスキャンします。

MYSQL EXPLAIN- MYSQL EXPLAIN Statement

私ははありません成功で2回照会し変更しました。 変形例1:

SELECT SUM(sale_data.total_sale) as totalsale, `sale_data_temp`.`customer_type_cy` as `customer_type`, `distributor_list`.`customer_status` FROM `distributor_list` LEFT JOIN `sale_data` ON `sale_data`.`depo_code` = `distributor_list`.`depo_code` and `sale_data`.`customer_code` = `distributor_list`.`customer_code` AND `invoice_date` BETWEEN "2017-04-01" and "2017-11-01" LEFT JOIN `sale_data_temp` ON `distributor_list`.`address_coordinates` = `sale_data_temp`.`address_coordinates` LEFT JOIN `item_master` ON `sale_data`.`item_code` = `item_master`.`item_code` WHERE `item_master`.`id_category` = 1 GROUP BY `distributor_list`.`address_coordinates` 

変更HERE 2

SELECT SQL_NO_CACHE SUM(sd.total_sale) AS totalsale, `sale_data_temp`.`customer_type_cy` AS `customer_type` , `distributor_list`.`customer_status` FROM `distributor_list` LEFT JOIN (SELECT * FROM `sale_data` WHERE `invoice_date` BETWEEN "2017-04-01" AND "2017-11-01")sd ON `sd`.`depo_code` = `distributor_list`.`depo_code` AND `sd`.`customer_code` = `distributor_list`.`customer_code` LEFT JOIN `sale_data_temp` ON `distributor_list`.`address_coordinates` = `sale_data_temp`.`address_coordinates` LEFT JOIN `item_master` ON `sd`.`item_code` = `item_master`.`item_code` WHERE `item_master`.`id_category` =1 GROUP BY `distributor_list`.`address_coordinates` 

特売データテーブルON MY INDEXES mysql EXPLAIN AND INDEXES IMAGE

+0

'func'はデータ型や照合に矛盾があるようです。 –

+1

私たちを助けてください - 2つの選択をフォーマットし、違いを指してください。 –

答えて

1

EXPLAIN結果ビューのkey欄をご覧ください - キーがありません現在使用されているので、MySQLは行をフィルタリングするためにインデックスを使用していないので、クエリごとにテーブル全体をスキャンしています。これは、それがずっと時間がかかる理由です。

私はあなたのsale_dataインデックスに関連して、あなたの最初のクエリを見てきました。あなただけの次の列が含まれています。このテーブルに新しい複合インデックスを作成する必要がありますように見えます:

depo_codecustomer_codeitem_codeinvoice_date、私はあなたがこのインデックスtest1と実験と名前を付けることをお勧めしますtotal_sale

列の順序を変更し、key列でインデックスtest1が選択されていることを確認したい場合は、EXPLAIN EXTENDEDを使用して毎回テストを再開します。

はこれを前に、私を助けてくれたthis answerを参照してください、そして、それはあなたが正しくあなたの複合指標を注文することの重要性を理解するのに役立ちます。

ALTER TABLE `sale_data` ADD INDEX `test1` (`item_code`, `customer_code`, `invoice_date`, `depo_code`, `total_sale`); 

幸運あなたの使命:ここでは、単一フィールドインデックスのカーディナリティを見ると

はあなたに適用する正しい指標を与えるで私の最高の試みです!

+0

私はその複数のインデックスを作ろうとしました。それは、可能なキーでtest1と請求書の日付を表示しますが、使用しません。 –

+0

'EXPLAIN'に基づいて、'それは 'WHERE'節で唯一のものなので、' invoice_date'はその "カバリング"インデックスの先頭にあるべきです。 –

+0

索引にtotalsaleを追加すると問題が解決されました。スキャンされた行は400000から92000に縮小されましたが、それでも同じ時間がかかります。 –

0

あなたのクエリについては、注意すべき点がいくつかあります。

  1. あなたはnotorious MySQL extension to GROUP BYを悪用しています。 Read thisの場合は、SELECT句に記載されているとおり、GROUP BY句に同じ列を記述してください。

  2. LEFT JOIN sale_dataLEFT JOIN item_master操作は実際には通常の操作です。JOIN操作です。どうして? WHERE句には、これらのテーブルの列があります。

  3. インデックスの日付範囲スキャンをsale_data.invoice_dateにするのが最善の方法です。何らかの理由でMySQLのクエリプランナーの熱狂的な方法だけが分かっていたとしても、あなたはそれを知りません。

リファクタリングをお試しください。

SELECT SUM(sale_data.total_sale) as totalsale, 
     sale_data_temp.customer_type_cy as customer_type, 
     distributor_list.customer_status 
    FROM distributor_list 
    JOIN sale_data 
      ON sale_data.invoice_date BETWEEN "2017-04-01" and "2017-11-01" 
      and sale_data.depo_code = distributor_list.depo_code 
      and sale_data.customer_code = distributor_list.customer_code 
    LEFT JOIN sale_data_temp 
      ON distributor_list.address_coordinates = sale_data_temp.address_coordinates 
    JOIN item_master 
      ON sale_data.item_code = item_master.item_code 
WHERE item_master.id_category = 1 
GROUP BY sale_data_temp.customer_type_cy, distributor_list.customer_status 

sale_dataにこのクエリのカバーインデックスを作成してみてください。あなたはこの権利を得るためにちょっと混乱しなければなりませんが、これは出発点です。 (invoice_date, item_code, depo_code, customer_code, total_sale)。カバリングインデックスのポイントは、テーブルのデータを参照しなくても、クエリーがインデックスの完全にであることを可能にすることです。だからこそ私はtotal_saleをインデックスに入れました。

私の提案するインデックスは、invoice_dateのインデックスを冗長にすることに注意してください。そのインデックスを削除することができます。

+0

totalsaleを含むあなたの指摘したインデックスを使用しました。売り上げデータの行は400000から92000に減少しました。しかし、phpmyadminでクエリを実行すると、説明SQLの売り上げデータの行が減っているにもかかわらず、7.5秒と同じ時間がかかります。 –