私はこれに似た構造を持っています:
CREATE TABLE `author` (
`id` int(11) unsigned NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;
CREATE TABLE `book` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`author_id` int(11) unsigned NOT NULL,
`org` int(11) unsigned NOT NULL,
`country` char(3) NOT NULL,
`publish_date` date NOT NULL,
`price` decimal(6,2) NOT NULL,
PRIMARY KEY (`id`),
KEY `author_id` (`author_id`),
KEY `publish_date` (`publish_date`),
KEY `i0` (`country`, `org`, `author_id`, `price`, `publish_date`),
KEY `i1` (`country`, `org`, `author_id`, `publish_date`, `price`)
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;
これが SQL Fiddle です
だから私は2つの範囲条件でクエリを実行しようとしています
SELECT
id as author_id,
(SELECT COUNT(DISTINCT `book`.`id`)+1
FROM `book`
WHERE
`book`.`org` = 1
AND `book`.`country` = 'USA'
AND `book`.`publish_date` BETWEEN '2010-04-30' AND '2011-04-30'
AND `book`.`author_id` = `author`.`id`
AND `book`.`price` < 50
) AS `books_under_fifty`
FROM `author`
ORDER BY books_under_fifty desc;
しかし、オプティマイザは私のインデックスの一部のみを使用します:const,const,db_9_6349e2.author.id
からi0
それを最適化する方法はありますか?
サブクエリをLEFT JOIN
およびGROUP BY
に変更できます。
SELECT
author.id as author_id, (count(distinct book.id) + 1) AS books_under_fifty
FROM
author
LEFT JOIN book ON
book.author_id = author.id
AND book.org = 1
AND book.country = 'USA'
AND book.publish_date BETWEEN '2010-04-30' and '2011-04-30'
AND book.price < 50
GROUP BY
author.id
ORDER BY
books_under_fifty desc, author_id;
...しかし、実行計画に関しては実際には何の違いもありません。
dbfiddleですべてを確認できます here
だから、私は恐らく答えはであり、それ以上最適化することはできません。いずれにしても、私が使用したシミュレーションではなく、実際のデータでテストすることをお勧めします。
ノート:
LEFT JOIN
のバリエーションも確認できます。
SELECT
author.id as author_id, coalesce(ccc, 1) AS books_under_fifty
FROM
author
LEFT JOIN
(SELECT
author_id, count(distinct book.id) + 1 AS ccc
FROM
book
WHERE
book.org = 1
AND book.country = 'USA'
AND book.publish_date BETWEEN '2010-04-30' and '2011-04-30'
AND book.price < 50
GROUP BY
author_id
) AS q0
ON q0.author_id = author.id
ORDER BY
books_under_fifty desc, author_id;
しかし、ここでも、MariaDBが何の利点も得ていないようです。
dbfiddle ここ
別のオープンソースデータベース(PostgreSQL 9.6)は、はるかに洗練された方法で処理を行うことができ、実行計画をはるかに優れたものにすることができます...(そしておそらく、より高速ですが、MariaDBはタイミングを取得しませんでした)。
PostgreSQLはLEFT JOIN
をより高速に動作させることができます(ほとんどの場合、各実行のランダム性に依存しますが)。
dbfiddle ここ