2016-07-13 3 views
0

ビュー 'goldedRunQueries'と 'currentGoldMarkings'を参照する以下の問合せがあります。私の問題はサブクエリで参照されているビューからのようです - currentGoldMarkings。実行中に、MySQLはまずこのサブクエリを具体化し、 'queryCode'と 'runId'のwhere句を実装します。その結果、ビューは何百万行ものデータ行を持つビューを参照するため、1時間以上の実行時間になります。私の質問は、サブクエリの条件が具体化される前に、それらの2つをどのように強制するのかです。は、マテリアライズド・サブクエリの外部問合せから条件を指定します。

SELECT goldedRunQueries.queryCode, goldedRunQueries.runId 
    FROM goldedRunQueries 
    LEFT OUTER JOIN 
     (SELECT measuredRunId, queryCode, COUNT(resultId) as c 
      FROM currentGoldMarkings 
      GROUP BY measuredRunId, queryCode 
    ) AS accuracy ON accuracy.measuredRunId = goldedRunQueries.runId 
     AND accuracy.queryCode = goldedRunQueries.queryCode 
    WHERE goldedRunQueries.queryCode IN ('CH001', 'CH002', 'CH003') 
     and goldedRunQueries.runid = 5000 
    ORDER BY goldedRunQueries.runId DESC, goldedRunQueries.queryCode; 

ここに2つのビューがあります。これらの両方ともスタンドアロンモードで使用されるため、それらに句を統合することはできません。

CREATE VIEW currentGoldMarkings 
AS 
SELECT result.resultId, result.runId AS measuredRunId, result.documentId, 
     result.queryCode, result.queryValue AS measuredValue, 
     gold.queryValue AS goldValue, 
     CASE result.queryValue WHEN gold.queryValue THEN 1 ELSE 0 END AS correct 
    FROM results AS result 
    INNER JOIN gold ON gold.documentId = result.documentId 
     AND gold.queryCode = result.queryCode 
    WHERE gold.isCurrent = 1 

CREATE VIEW goldedRunQueries 
AS 
SELECT runId, queryCode 
    FROM runQueries 
    WHERE EXISTS 
     (SELECT 1 AS Expr1 
      FROM runs 
      WHERE (runId = runQueries.runId) 
       AND (isManual = 0) 
    ) 
     AND EXISTS 
     (SELECT 1 AS Expr1 
      FROM results 
      WHERE (runId = runQueries.runId) 
       AND (queryCode = runQueries.queryCode) 
       AND EXISTS 
       (SELECT 1 AS Expr1 
        FROM gold 
        WHERE (documentId = results.documentId) 
         AND (queryCode = results.queryCode) 
      ) 
    ) 

注:上記のクエリは、実際のクエリの一部のみを反映しています。問題をはるかに悪化させる上記のサブクエリに似ている他の3つの左外部結合があります。

EDIT:示唆したように、ここでの構造といくつかのサンプルデータは、テーブルのためである

CREATE TABLE `results`(
`resultId` int auto_increment NOT NULL, 
`runId` int NOT NULL, 
`documentId` int NOT NULL, 
`queryCode` char(5) NOT NULL, 
`queryValue` char(1) NOT NULL, 
`comment` varchar(255) NULL, 
CONSTRAINT `PK_results` PRIMARY KEY 
(
`resultId` 
) 
); 


insert into results values (100, 242300, 'AC001', 'I', NULL) 
insert into results values (100, 242300, 'AC001', 'S', NULL) 
insert into results values (150, 242301, 'AC005', 'I', 'abc') 
insert into results values (100, 242300, 'AC001', 'I', NULL) 
insert into results values (109, 242301, 'PQ001', 'S', 'zzz') 
insert into results values (400, 242400, 'DD006', 'I', NULL) 



CREATE TABLE `gold`(
`goldId` int auto_increment NOT NULL, 
`runDate` datetime NOT NULL, 
`documentId` int NOT NULL, 
`queryCode` char(5) NOT NULL, 
`queryValue` char(1) NOT NULL, 
`comment` varchar(255) NULL, 
`isCurrent` tinyint(1) NOT NULL DEFAULT 0, 
CONSTRAINT `PK_gold` PRIMARY KEY 
(
`goldId` 
) 
); 



insert into gold values ('2015-02-20 00:00:00', 138904, 'CH001', 'N', NULL, 1) 
insert into gold values ('2015-05-20 00:00:00', 138904, 'CH001', 'N', 'aaa', 1) 
insert into gold values ('2016-02-20 00:00:00', 138905, 'CH002', 'N', NULL, 0) 
insert into gold values ('2015-12-12 00:00:00', 138804, 'CH001', 'N', 'zzzz', 1) 



CREATE TABLE `runQueries`(
`runId` int NOT NULL, 
`queryCode` char(5) NOT NULL, 
CONSTRAINT `PK_runQueries` PRIMARY KEY 
(
`runId`, 
`queryCode` 
) 
); 


insert into runQueries values (100, 'AC001') 
insert into runQueries values (109, 'PQ001') 
insert into runQueries values (400, 'DD006') 



CREATE TABLE `runs`(
`runId` int auto_increment NOT NULL, 
`runName` varchar(63) NOT NULL, 
`isManual` tinyint(1) NOT NULL, 
`runDate` datetime NOT NULL, 
`comment` varchar(1023) NULL, 
`folderName` varchar(63) NULL, 
`documentSetId` int NOT NULL, 
`pipelineVersion` varchar(50) NULL, 
`isArchived` tinyint(1) NOT NULL DEFAULT 0, 
`pipeline` varchar(50) NULL, 
CONSTRAINT `PK_runs` PRIMARY KEY 
(
`runId` 
) 
); 


insert into runs values ('test1', 0, '2015-08-04 06:30:46.000000', 'zzzz', '2015-08-04_103046', 2, '2015-08-03', 0, NULL) 
insert into runs values ('test2', 1, '2015-12-04 12:30:46.000000', 'zzzz', '2015-08-04_103046', 2, '2015-08-03', 0, NULL) 
insert into runs values ('test3', 1, '2015-06-24 10:56:46.000000', 'zzzz', '2015-08-04_103046', 2, '2015-08-03', 0, NULL) 
insert into runs values ('test4', 1, '2016-05-04 11:30:46.000000', 'zzzz', '2015-08-04_103046', 2, '2015-08-03', 0, NULL) 
+0

好きな人は、適切なCREATEステートメントとINSERTステートメントと望ましい結果を提供することを検討してください。 – Strawberry

+0

@Strawberryごめんなさい。オブジェクトのCREATE文とINSERT文 – PratikGandhi

+0

'goldedRunQueries'と' currentGoldMarkings'を構築するために使用されるテーブルは私にとっては明らかな候補のようです - 'results'、' gold'、 'runs'、' runQueries' – Strawberry

答えて

1

まずは、インデックスを経由して、パフォーマンスを向上させるために試してみましょう:

結果:INDEX(RUNID、queryCode) - いずれかの順序 金に:INDEX(文書ID、query_code、isCurrent) - の順でその後

、問題のCREATE TABLEsを更新し、出力の追加:

EXPLAIN EXTENDED SELECT ...; 
SHOW WARNINGS; 

どのバージョンを実行していますか?あなたは事実上FROM (SELECT ...) JOIN (SELECT ...)を持っています。 5.6より前には、どちらのサブクエリもインデックスを持っていませんでした。 5.6では、オンザフライでインデックスが生成されます。

どちらのクエリを使用するかわかっているので、クエリはそのように構築されています。and goldedRunQueries.runid = 5000です。

ボトムライン:インデックスを追加します。 5.6または5.7にアップグレードします。それで十分でない場合は、VIEWsの使用を再考してください。

+0

よく、私はビューをストアドプロシージャを呼び出し、パラメータを使用して条件を渡すことができるようになりました。 @RickJamesあなたが金のテーブルのために与えたインデックスの順序についての素早い質問です - 最初の列として 'isCurrent'を持っていないのはなぜですか? – PratikGandhi

+0

最後のサブクエリには 'iscurrent'はありません。最初の2列は有益です。 –

関連する問題