2017-02-04 21 views
0

私は辛抱強く実行されるクエリを持っており、パフォーマンスを向上させる方法についていくつかアドバイスが必要です。MySQLのクエリパフォーマンスの改善?

最初のテーブル:結果は約10k行です。

'CREATE TABLE `results` (
`ID` bigint(20) NOT NULL AUTO_INCREMENT, 
`matchID` int(11) NOT NULL, 
`matchShooterID` int(11) NOT NULL DEFAULT ''0'', 
`ResultDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
... more columns ... 
PRIMARY KEY (`ID`) 
) ENGINE=InnoDB AUTO_INCREMENT=9767 DEFAULT CHARSET=latin1' 

インデックス

Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment 
'results', '0', 'PRIMARY', '1', 'ID', 'A', '3462', NULL, NULL, '', 'BTREE', '', '' 

第二表:wp_usermetaは約10K行があります。ここで

'CREATE TABLE `wp_usermeta` (
    `umeta_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, 
    `user_id` bigint(20) unsigned NOT NULL DEFAULT ''0'', 
    `meta_key` varchar(255) DEFAULT NULL, 
    `meta_value` longtext, 
    PRIMARY KEY (`umeta_id`), 
    KEY `user_id` (`user_id`), 
    KEY `meta_key` (`meta_key`(191)) 
) ENGINE=InnoDB AUTO_INCREMENT=11170 DEFAULT CHARSET=utf8'; 

Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment 
wp_usermeta 0 PRIMARY 1 umeta_id A 6241    BTREE  
wp_usermeta 1 user_id 1 user_id A 780    BTREE  
wp_usermeta 1 meta_key 1 meta_key A 104 191  YES BTREE  

は私のクエリです:

SELECT DISTINCT 
     pr.ShooterID AS ShooterID, 
     pr.RangeID AS RangeID, 
     (SELECT um.meta_value 
      FROM 
       wp_usermeta um 
      WHERE 
       ((um.meta_key = 'first_name') 
        AND (um.user_id = pr.ShooterID))), 
     (SELECT 
       COUNT(0) 
      FROM 
       wp_plinker_results 
      WHERE 
       ((results.ShooterID = pr.ShooterID) 
        AND (results.RangeID = pr.RangeID))) AS GameCount 
FROM 
    (results pr 
    JOIN wp_usermeta um ON ((pr.ShooterID = um.user_id))); 

私は何を取得しようとしていることは日によって各shooterIDのためのゲームの数(結果レコード)です。どんな提案も大歓迎です。

更新

:あなたはすでにwp_usermetaに参加していますので、出力とインデックスが

1 PRIMARY pr ALL     3462 100.00 Using temporary 
1 PRIMARY um ref user_id user_id 8 shootpli_plpress.pr.ShooterID 8 100.00 Using where; Using index; Distinct 
3 DEPENDENT SUBQUERY wp_plinker_results ALL     3462 100.00 Using where 
2 DEPENDENT SUBQUERY um ref user_id,meta_key user_id 8 shootpli_plpress.pr.ShooterID 8 100.00 Using index condition; Using where 
+0

私たちにあなたのインデックスが何であるか教えてください。また、 'explain'の結果。また、クエリーが何を達成しているかの説明は、それを書き直すのに役立ちます。 – Schwern

+0

2番目のサブクエリは 'results.ShooterID = pr.ShooterID'ですが、' pr'は 'results'にエイリアスされています。 – Schwern

+0

これを正しく読んでいれば、 'results'には外部キーインデックスはありませんか?それはパフォーマンスの問題を引き起こすでしょう。 – Schwern

答えて

1

を追加EXPLAIN、あなたはパフォーマンスを向上させるためにlinker_resultsに参加する必要があり

SELECT pr.ShooterID AS ShooterID, 
      pr.RangeID AS RangeID, 
      CASE um.meta_key WHEN um.meta_key ='first_name' THEN um.meta_value ELSE 'NO_META_VALUE' END as meta_value, 
      COUNT(0) AS GameCount 
    FROM 
     results pr 
     JOIN wp_usermeta um ON ((pr.ShooterID = um.user_id)) 
     JOIN wp_plinker_results um ON ((results.ShooterID = pr.ShooterID) 
        AND (results.RangeID = pr.RangeID)) 
    GROUP BY pr.ShooterID,pr.RangeID,um.meta_value; 
+0

入力してくれてありがとう...私はそれを逃した... –

1

あなたは、MySQL 5.7へのアクセスを持っている場合.8またはそれより新しい場合、wp_usermetaテーブルは、userテーブルのJSONカラムとしてうまくいくでしょう。

クエリにはresultsprが混在していますが、これらは同じテーブルのエイリアスです。 prはおそらくwp_plinker_resultsのエイリアスにする必要があります。


すでにwp_usermetaに参加しているので、最初のサブクエリは単純なwhere句に置き換えることができます。

WHERE um.meta_key = 'first_name' 

次に、um.meta_value AS FirstNameを選択できます。

は私が
SELECT DISTINCT 
     results.ShooterID AS ShooterID, 
     results.RangeID AS RangeID, 
     um.meta_value AS FirstName, 
     COUNT(pr.id) AS GameCount 
FROM results 
JOIN wp_usermeta um ON um.user_id = results.ShooterID 
JOIN wp_plinker_results pr ON results.ShooterID = pr.ShooterID AND 
           results.RangeID = pr.RangeID 
WHERE um.meta_key = 'first_name' 
GROUP BY pr.ShooterID, pr.RangeID 

この

は、MySQLが最適化するためにはるかに容易になります... 2番目のサブクエリにも参加し、

JOIN wp_plinker_results pr ON results.ShooterID = pr.ShooterID AND 
           results.RangeID = pr.RangeID 
GROUP BY pr.ShooterID, pr.RangeID 

によってグループすべて一緒にそれを入れて行うことができると信じて。

すべての外部キーがインデックスされているように宣言されていることは非常に重要です。 um.meta_keyの索引付けも重要です。

1

WP、起床!あなたのインデックスは問題です!

PRIMARY KEY (`umeta_id`), 
KEY `user_id` (`user_id`), 
KEY `meta_key` (`meta_key`(191)) 

- >

umeta_idを取り除く - 列とインデックスの両方 - それは無用である、物事を遅くします。

PRIMARY KEY(user_id, meta_key), -- to speed up the main query 
INDEX(meta_key) -- if needed for other queries 

COUNTJOIN、及びGROUP BY混合に注意。 JOINが行の数を膨らませた場合、が再度収縮する前に、COUNTが発生し、値が大きくなります。 DISTINCTGROUP BYを混用しないでください。後者は効果的に前者を行います。

(あまりにも、SHOW CREATE TABLE wp_plinker_resultsを見て参考になる。)

私はwp_plinker_resultsの目的が表示されていないので、私はそれを削除しました。

SELECT r.ShooterID, 
     r.RangeID, 
     DATE(r.ResultDate) AS date, 
     (SELECT meta_value 
      FROM wp_usermeta 
      WHERE user_id = r.ShooterID 
       AND meta_key = 'first_name' 
     ) AS FirstName, 
     COUNT(*) AS GameCount 
FROM results AS r 
GROUP BY r.ShooterID, r.RangeID, DATE(r.ResultDate) 

それはresultsのために、このインデックスを持っていることが有用であり得る:

INDEX(ShooterID, RangeID, ResultDate) 

results.ShooterIDresults.matchShooterIdことになっていますか? (そして、疑問には不明なことが他にもあります!)

+0

入力していただきありがとうございます。私は現在、FKを追加する権限がないので、私のホスティングプロバイダと私の尻尾を追いかけています!うまくいけば、それはすぐに解決されるでしょう。 – cce1911

+0

FKはデータベースの要件ではありません。あなたには特別な必要がありますか? –

+0

親テーブルの主キーが自動インクリメントに設定されていることが判明しました。このため、MySqlはPKの追加を許可しません。これは私に、パフォーマンスを改善するためにPKを必要としないソリューションを探すことを余儀なくさせました。これに基づいて、Mitの答えは正しい方向で私に指摘していました。そして今、私のクエリのパフォーマンスは受け入れられます。返事をいただいた皆様に感謝します! – cce1911

関連する問題