2016-06-21 7 views
3

テーブル内のいくつかの行を更新しています。クエリの実行に時間がかかります。 以下のクエリの実行パフォーマンスを向上させるにはどうすればよいですか?どのようにmysqlクエリのパフォーマンスを向上させるには?

update org_products op 
inner join access_history 
    on access_history.access_key = op.id and access_history.access_type = "OrgProduct.View" 
set views = 
(
    select count(access_key) 
    from access_history 
    where access_history.access_key = op.id and 
      access_history.created_at >= DATE_SUB(CURDATE(), INTERVAL 90 DAY) and 
      access_history.access_type = "OrgProduct.View" and 
      access_history.product_id = op.product_id 
    GROUP BY access_history.product_id 
) 
where access_history.access_key = op.id and 
     access_history.access_type = "OrgProduct.View"; 

更新:SHOW CREATE TABLE access_history;

'access_history', 'CREATE TABLE `access_history` (
\n `id` bigint(20) NOT NULL AUTO_INCREMENT, 
\n `product_id` bigint(20) unsigned NOT NULL, 
\n `access_type` varchar(50) DEFAULT NULL, 
\n `access_key` varchar(50) DEFAULT NULL, 
\n `access_key_full` varchar(200) DEFAULT NULL, 
\n `client_ip_addr` varbinary(16) DEFAULT NULL, 
\n `userid` bigint(20) unsigned DEFAULT NULL,\n `username` tinytext, 
\n `anon_user_id` bigint(20) unsigned DEFAULT NULL, 
\n `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
\n `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`id`), 
\n KEY `fk_access_history_has_product_product1_idx` (`product_id`), 
\n KEY `idx_access_history_prod_type_key` (`product_id`,`access_type`,`access_key`), 
\n CONSTRAINT `fk_access_history_has_product_product1_idx` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`) ON 
DELETE NO ACTION ON UPDATE NO ACTION\n) ENGINE=InnoDB AUTO_INCREMENT=1290353 DEFAULT CHARSET=utf8' 

出力のSHOW INDEX from access_history; enter image description here

出力EXPLAIN query出力enter image description here

パフォーマンスを向上させるには、どのような変更が必要ですか?

ありがとうございました!ありがとう!

+0

あなたの参加条件と外部条件が同じです。私は最初にjoin句から2番目の条件を削除し、where句から最初の条件を削除します。 –

+0

'WHERE'節にはいくつかの繰り返し基準があります。あなたの場合にそれが必要かどうかは分かりません。サンプルデータを提供できるのであれば良いでしょう。 – ydoow

+0

@TimBiegeleisen:すぐにお返事ありがとうございます!私はあなたが提案したものを試しましたが、結果は同じです。 –

答えて

1

2つの変異体は、ここにあります

1)あなたはCRONで定期的に議論し、クエリを実行する - あなたはそのアクセス歴史の最後の90日以内に変更されたすべての製品を更新するようにします。次のクエリを試してみてください(事前に開始日を計算してからこの定数値を使用する方がよいでしょう)。DATE_SUB()を使用すると、これは動的な値であると考えるようになり、毎回計算します。 )定数:

UPDATE org_products op 
    SET views = (SELECT COUNT(*) FROM access_history 
     WHERE access_key = op.id 
      AND access_type = "OrgProduct.View" 
    ) 
    WHERE op.id IN (SELECT access_key FROM access_history 
     WHERE access_type = "OrgProduct.View" 
      AND created_at >= "YYYY-MM-DD" 
    ) 

2)あなたは、テーブルにaccess_history各挿入後に議論してクエリを実行 - (以下ACCESS_KEY_VALUEは、あなただけのテーブルにaccess_history)を挿入したもので試してみてください。

UPDATE org_products op 
    SET views = (SELECT COUNT(*) FROM access_history 
     WHERE access_key = ACCESS_KEY_VALUE 
      AND access_type = "OrgProduct.View" 
    ) 
    WHERE op.id = ACCESS_KEY_VALUE 

どちらの場合も、私は別のテーブルに列access_typeのすべての個別の文字列を移動し、列をINTに変換して、その新しいテーブルに外部キーにすることをお勧めします。その理由は、数値の索引付けと比較が文字列の比較よりも速いためです。

関連する問題