ソリューション B
私は@Strawberryの回答を受け入れましたが、この解決策は投稿自体の問題ではないため、回答としては書きませんが、役に立つかもしれない人にはここに残してください。
主な問題は、クエリのパフォーマンスと構造の問題です。私がすべての属性を検索しslides
、その後結果を制限しているという事実は、それを非常に遅くしています。解決策は、最初に取得したいスライドを取得してから、その短い結果セットから余分な情報をすべて検索することです。
したがって、最終的なクエリ (0.2 秒未満で実行され、必要なすべての結果が得られる) は次のようになります。
SELECT
sl.slide_id AS slide_id,
sl.time_in AS time_in,
sl.time_out AS time_out,
sl.duration AS duration,
sl.slide_order AS slide_order,
sl.title AS title,
sl.slide_type AS slide_type,
sl.report_id AS report_id,
sltg.tag_category_id AS tag_category_id,
sltg.tag_value_id AS tag_value_id,
sltgc.txt AS tag_category_text,
sltgv.txt AS tag_value_text,
FROM (SELECT
sl.time_in AS time_in,
sl.time_out AS time_out,
sl.duration AS duration,
sl.slide_order AS slide_order,
sl.media_id AS media_id,
sl.title AS title,
sl.slide_type AS slide_type,
slrep.report_id AS report_id,
slrep.slide_id AS slide_id
FROM er_slides sl
INNER JOIN er_slides_in_report slrep
ON slrep.slide_id = sl.unique_id
AND slrep.report_id IN (1461317308472,1461597566425,1461598458236)
AND slrep.deleted_date IS NULL
LIMIT 0, 5
) sl
INNER JOIN er_slides_tags sltg
ON sltg.deleted_date IS NULL
AND sltg.slide_id = sl.slide_id
INNER JOIN er_slide_tags_categories sltgc
ON sltgc.id = sltg.tag_category_id
INNER JOIN er_slide_tags_values sltgv
ON sltgv.id = sltg.tag_value_id
ORDER BY slide_id, tag_value_id;
ご覧のとおり、他のものを検索する前にセットを制限します。その後、クエリは非常に高速に実行されます。このアプローチが、誰かが自分のクエリを改善するのに役立つことを願っています.
元の質問
いくつかのコンテナー (レポート) にグループ化されたいくつかの要素 (スライド) を含むテーブルがあり、これらの要素のそれぞれにいくつかの属性 (タグ値) とカテゴリ (タグ カテゴリ) が割り当てられています。これは、要素 X がカテゴリ Z のタグ Y を持つことができるタグ付けシステムのようなものです。
データベース構造
CREATE TABLE IF NOT EXISTS `er_reports` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`unique_id` varchar(64) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`name` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`user_id` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
`author` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL,
`report_status` varchar(32) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'incomplete',
`num_slides` int(4) NOT NULL DEFAULT '0',
`report_type` varchar(25) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'report',
`target_id` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
`created_date` datetime DEFAULT NULL,
`uploaded_date` datetime DEFAULT NULL,
`deleted_date` datetime DEFAULT NULL,
`modified_date` datetime DEFAULT NULL,
`item_reference` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
`is_favourite` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `unique_id` (`unique_id`),
KEY `unique_id_2` (`unique_id`),
KEY `unique_id_3` (`unique_id`),
KEY `user_id` (`user_id`),
KEY `deleted_date` (`deleted_date`),
KEY `is_favourite` (`is_favourite`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=714 ;
CREATE TABLE IF NOT EXISTS `er_slides` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`unique_id` varchar(64) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`report_id` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
`action_id` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
`media_id` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
`thumbnail_id` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
`media_offset` int(6) NOT NULL DEFAULT '0',
`time_in` decimal(9,3) DEFAULT NULL,
`time_out` decimal(9,3) DEFAULT NULL,
`duration` decimal(9,3) NOT NULL DEFAULT '10.000',
`title` text COLLATE utf8_unicode_ci,
`slide_comment` text COLLATE utf8_unicode_ci,
`note_id` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
`content` text COLLATE utf8_unicode_ci,
`media_object` text COLLATE utf8_unicode_ci,
`slide_type` varchar(32) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'action',
`user_id` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
`slide_order` int(4) NOT NULL DEFAULT '0',
`count_slide` tinyint(1) NOT NULL DEFAULT '1',
`visible` tinyint(1) NOT NULL DEFAULT '1',
`deleted_date` datetime DEFAULT NULL,
`created_date` datetime DEFAULT NULL,
`uploaded_date` datetime DEFAULT NULL,
`modified_date` datetime DEFAULT NULL,
`item_reference` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `unique_id` (`unique_id`),
KEY `report_id` (`report_id`),
KEY `deleted_date` (`deleted_date`),
KEY `action_id` (`action_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=31899 ;
CREATE TABLE IF NOT EXISTS `er_slides_in_report` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`report_id` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
`slide_id` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
`slide_order` int(3) NOT NULL DEFAULT '1',
`added_date` datetime DEFAULT NULL,
`modified_date` datetime DEFAULT NULL,
`deleted_date` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `report_id` (`report_id`,`slide_id`,`deleted_date`),
KEY `slide_order` (`slide_order`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=16843 ;
CREATE TABLE IF NOT EXISTS `er_slides_tags` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`slide_id` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
`tag_category_id` bigint(20) NOT NULL,
`tag_value_id` bigint(20) NOT NULL,
`created_date` datetime NOT NULL,
`deleted_date` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `slide_id` (`slide_id`,`tag_category_id`,`tag_value_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=220623 ;
CREATE TABLE IF NOT EXISTS `er_slide_tags_categories` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`txt` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `txt` (`txt`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=17 ;
CREATE TABLE IF NOT EXISTS `er_slide_tags_values` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`txt` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `txt` (`txt`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=439 ;
私が試したこと
SELECT @slide_num := if(@sl_id = slrep.slide_id collate utf8_unicode_ci, @slide_num, @slide_num := @slide_num+1) as slide_num,
@sl_id := slrep.slide_id collate utf8_unicode_ci as sl_id,
slrep.report_id AS report_id,
slrep.slide_id AS slide_id,
sltg.tag_category_id AS tag_category_id,
sltg.tag_value_id AS tag_value_id,
sltgc.txt AS tag_category_text,
sltgv.txt AS tag_value_text,
sl.time_in AS time_in,
sl.time_out AS time_out,
sl.duration AS duration,
sl.slide_order AS slide_order,
sl.title AS title,
sl.slide_type AS slide_type
FROM (SELECT @sl_id:=1, @slide_num := 0) v, er_slides sl
INNER JOIN er_slides_in_report slrep
ON slrep.slide_id = sl.unique_id
AND slrep.report_id IN (1461317308472,1461597566425,1461598458236)
AND slrep.deleted_date IS NULL
INNER JOIN er_slides_tags sltg
ON sltg.deleted_date IS NULL
AND sltg.slide_id = sl.unique_id
INNER JOIN er_slide_tags_categories sltgc
ON sltgc.id = sltg.tag_category_id
INNER JOIN er_slide_tags_values sltgv
ON sltgv.id = sltg.tag_value_id
WHERE @slide_num >= 0 AND @slide_num <= 5
ORDER BY slide_id, tag_value_id;
クエリがどのように構築されているかを確認できるように、いくつかの偽のレポート ID を用意しました。
問題
問題は、これでは十分な速度ではないことです。5 枚のスライド、200 行の情報を取得するのに約 3 秒かかります。また、from limitを変更できません。私が書く場合:
WHERE @slide_num >= 10 AND @slide_num <= 15
空の結果が得られます (もちろん、十分な数のスライドがあることを確認しました)。
200行を取得するのに3秒かかる理由もわかりません。
必要なもの
可能な限り最速の方法で、選択した範囲内にあるスライドのみを動的にクエリできるようにする必要があります。
何か足りないものを見つけた場合は、投稿できるようにコメントしてください。
ありがとうございました。
編集:クエリの説明(ストロベリーアプローチ)
@strawberry が示唆したように、私は彼のアプローチを適用しようとしました。ただし、クエリの応答時間は、書き込みよりBETWEEN 0 AND 5
も書き込み範囲が同じですBETWEEN 0 AND 200
(両方とも約 17 秒)。
これは不適切なインデックス付けが原因である可能性があるため、不適切なインデックス付けが見られないため、ここに記述することにしました (句にEXPLAIN
入れられたすべての条件にはインデックスがあります)。WHERE