1

問題

次のクエリは、次の場合を除いて、実行に30秒以上かかります。

  • 並べ替えを削除します(クエリしてから1秒未満)
  • 個別のキーワードを削除します:(クエリしてから1秒未満)
  • 結合の削除を開始します(クエリしてから5秒未満)

質問

このクエリを1秒以内に実行するにはどうすればよいですか。必須:ある種の種類を含む、以下の参加で説明されているように、関連データを含む会議の一意のリストを取得するにはどうすればよいですか。

関連データは、関連フィールドがあるかどうかの判断とGROUP_CONCAT操作の実行の両方に使用されます。したがって、同じbookeditemsテーブルに3つの異なる結合が必要です。

ヘルプや提案を事前に感謝します!私はこれに数時間頭をぶつけてきました!

クエリ

SELECT

DISTINCT( `meetings`.`id` ) AS `meeting_id`,
`meetings`.`uid` AS meeting_uid,
`meetings_SERV`.`id` AS meetings_SERV_id, 
`meetings_TRANSP`.`id` AS meetings_TRANSP_id, 
`meetings_ACCO`.`id` AS meetings_ACCO_id, 
`meetings_BOOKEDITEMS`.`id` AS meetings_BOOKEDITEMS_id

FROM `meetings` AS meetings 

LEFT OUTER JOIN `bookeditems` AS `meetings_SERV` 
ON `meetings`.`uid` = `meetings_SERV`.`meeting_uid`
AND 'SER' = `meetings_SERV`.`item_type` 

LEFT OUTER JOIN `bookeditems` AS `meetings_TRANSP` 
ON `meetings`.`uid` = `meetings_TRANSP`.`meeting_uid`
AND 'TRA' = `meetings_TRANSP`.`item_type` 

LEFT OUTER JOIN `bookeditems` AS `meetings_ACCO` 
ON `meetings`.`uid` = `meetings_ACCO`.`meeting_uid`
AND 'ACC' = `meetings_ACCO`.`item_type` 

LEFT OUTER JOIN `bookeditems` AS `meetings_BOOKEDITEMS` 
ON `meetings`.`uid` = `meetings_BOOKEDITEMS`.`meeting_uid` 

ORDER BY `meetings`.`datetime`

LIMIT 0, 50

テーブル定義

CREATE TABLE IF NOT EXISTS `bookeditems` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `meeting_uid` varchar(256) NOT NULL,
  `item_type` varchar(256) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `meeting_uid` (`meeting_uid`(255)),
  KEY `index1` (`meeting_uid`(255),`item_type`(255))
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=5889 ;

CREATE TABLE IF NOT EXISTS `meetings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` varchar(256) NOT NULL,
  `datetime` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `uid` (`uid`(255)),
  KEY `datetime` (`datetime`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=7487 ;

EXPLAINSELECTの結果

id | select_type | table                | type | possible_keys      | key         | key_len | ref                      | rows | Extra
-------------------------------------------------------------------------------------------------------------------------------------
1  | SIMPLE      | meetings             | ALL  | NULL               | NULL        | NULL    | NULL                     | 7483 | Using temporary; Using filesort
1  | SIMPLE      | meetings_SERV        | ref  | meeting_uid,index1 | meeting_uid | 767     | test.meetings.uid        | 1    | 
1  | SIMPLE      | meetings_TRANSP      | ref  | meeting_uid,index1 | meeting_uid | 767     | test.meetings.uid        | 1    | 
1  | SIMPLE      | meetings_ACCO        | ref  | meeting_uid,index1 | meeting_uid | 767     | test.meetings.uid        | 1    | 
1  | SIMPLE      | meetings_BOOKEDITEMS | ref  | meeting_uid,index1 | meeting_uid | 767     | test.meetings.uid        | 1    | 

プロファイリングの結果

starting                      0.000092
checking permissions          0.000003
checking permissions          0.000002
checking permissions          0.000001
checking permissions          0.000001
checking permissions          0.000003
Opening tables                0.000036
System lock                   0.000008
init                          0.000033
optimizing                    0.000005
statistics                    0.000035
preparing                     0.000019
Creating tmp table            0.000165
executing                     0.000004
Copying to tmp table          1.790968
converting HEAP to MyISAM     1.669041
Copying to tmp table on disk  28.32606
Sorting result                0.141737
Sending data                  0.000099
end                           0.000005
removing tmp table            0.022097
end                           0.000014
query end                     0.000008
closing tables                0.000017
freeing items                 0.000779
logging slow query            0.000004
cleaning up                   0.000005

パートソリューション

以下のEricR.Rathのヘルプに基づいて、クエリのプロファイルを作成し、max_heap_table_size = 256M&tmp_table_size = 256MをMySQL構成に追加することで、「HEAPからMyISAMへの変換」および「ディスク上のtmpテーブルへのコピー」の実行手順を排除できました。 "。

これは合計実行時間が2秒未満になりますが、クエリの最適化に関して他に提案がある場合は、これがすべてできるとはまだ確信していません。お知らせください。

max_heap_table_size&tmp_table_sizeconfigに続くプロファイリング

...
executing                     0.000004
Copying to tmp table          1.790968
Sorting result                0.141737
...
4

3 に答える 3

0

インデックスを確認しましょう。

bookeditemsのmeeting_idとitem_typeに複合インデックスがありますか?

会議の会議IDにインデックスがあり、それが複合キーにある場合、それは最初のインデックスですか?

会議の日時にクラスター化されたインデックスがありますか?

個別に行う代わりに、サブクエリを配置して、各会議IDのスタックの最上位を取得できますか?

何かのようなもの:

select * from meetings a
where datetime = (select max(datetime) from meetings 
where meetingid = a.meetingid)

左から参加する代わりに、会議の種類に対してcaseステートメントを使用して同じデータを取得できますか?

于 2012-06-08T14:07:12.900 に答える
0

index2は不要であり、削除できると思います。これはindex1のプレフィックスです。ただし、これによってクエリ時間が短縮されることはありません。

EXPLAIN出力は、本当の原因を示しています:「一時的なものの使用、ファイルソートの使用」。場合によっては、MySQLに、参加に使用したのと同じキーを使用して順序付けを実行させることで、これを回避できます。index1を(meeting_id、datetime)に変更すると、変更できる可能性があります。item_typeをindex1に保持する必要がある場合は、それをインデックスの3番目の列として追加するか、すべての値を含むIN()句をクエリに含めることができます。

于 2012-06-08T23:39:33.450 に答える
0

最初に関心のあるレコード(およびを使用)SELECTを-ingし、次にその結果を使用して他のテーブルと結合することにより、オプティマイザーを支援することができます。このアプローチを使用すると、インデックスonをおよび句に完全に使用できます。このアプローチは次のようになります。ORDER BYLIMITdatetimeORDER BYLIMIT

SELECT
  `meetings`.`id` AS `meeting_id`,
  `meetings`.`uid` AS meeting_uid,
  GROUP_CONCAT(
   DISTINCT CASE bookeditems.item_type
     WHEN 'SER' THEN bookeditems.id
     ELSE NULL
   END
  ) AS meetings_SERV_ids,
  GROUP_CONCAT(
   DISTINCT CASE bookeditems.item_type
     WHEN 'TRA' THEN bookeditems.id
     ELSE NULL
   END
  ) AS meetings_TRANSP_ids,
  GROUP_CONCAT(
   DISTINCT CASE bookeditems.item_type
     WHEN 'ACC' THEN bookeditems.id
     ELSE NULL
   END
  ) AS meetings_ACCO_ids,
  GROUP_CONCAT(bookeditems.id) AS meetings_BOOKEDITEMS_ids
FROM (
  SELECT id
  FROM meetings
  ORDER BY `datetime`
  LIMIT 0, 50
) filtered_meetings
INNER JOIN meetings
  ON meetings.id = filtered_meetings.id
LEFT OUTER JOIN bookeditems
  ON meeting_uid = bookeditems.meeting_uid
GROUP BY meeting_uid

注目すべき違い:

  • 予約アイテムテーブルに参加するのは1回のみです。GROUP_CONCATselectステートメントでは、 withステートメントを使用しCASEて、特定の基準に一致する会議グループ内のすべてのIDを選択します。GROUP BYさらに、これを機能させるには、同じ会議を表すすべての行をグループ化するステートメントを追加する必要があります。これは、、、、およびのIDの

    文字列を取得する可能性があることを意味します。したがって、結果行を処理するクライアントコードで、または同等のものを覚えておいてください。meetings_SERV_idsmeetings_TRANSP_idsmeetings_ACCO_idsmeetings_BOOKEDITEMS_idsexplode
于 2012-06-11T19:07:07.933 に答える