1
  1. 以下のクエリは、実行に約2分かかるため、このクエリのパフォーマンスを向上させる方法を教えてください。
  2. したがって、2〜3秒以内に結果を取得する必要があります。
  3. クエリもインデックスを使用しています。
  4. しかし、それはより多くのスキャンを実行していました。

クエリ:

select max(`log_date`)
from `top_competitor_summary_entity`
where
  own_domain_id = 4
  and keyword_top1_count > 0
  and (grouptag_id = 0 OR grouptag_id is null);

Expalinプラン:

+----+-------------+-------------------------------+------+--------------------------------------+------------------------+---------+-------+---------+-------------+
| id | select_type | table                         | type | possible_keys                        | key                    | key_len | ref   | rows    | Extra       |
+----+-------------+-------------------------------+------+--------------------------------------+------------------------+---------+-------+---------+-------------+
|  1 | SIMPLE      | top_competitor_summary_entity | ref  | own_domain_id,own_domain_id_log_date | own_domain_id_log_date | 4       | const | 2100128 | Using where |
+----+-------------+-------------------------------+------+--------------------------------------+------------------------+---------+-------+---------+-------------+
1 row in set (0.66 sec)

テーブル構造:

mysql> show create table top_competitor_summary_entity\G
*************************** 1. row ***************************
       Table: top_competitor_summary_entity
Create Table: CREATE TABLE `top_competitor_summary_entity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `domain` varchar(255) NOT NULL COMMENT 'competitor domain name',
  `own_domain_id` int(11) NOT NULL,
  `keyword_top10_count` int(11) DEFAULT NULL,
  `keyword_top3_count` int(11) DEFAULT NULL,
  `keyword_top1_count` int(11) DEFAULT NULL,
  `keyword_top10_search_volume` bigint(20) DEFAULT NULL,
  `keyword_top3_search_volume` bigint(20) DEFAULT NULL,
  `keyword_top1_search_volume` bigint(20) DEFAULT NULL,
  `url_top10_count` int(11) DEFAULT NULL
    COMMENT 'how many competitor url in Top 10',
  `log_date` date DEFAULT NULL,
  `grouptag_id` int(11) DEFAULT '0',
  `keyword_top10_count_bing` int(11) DEFAULT '0',
  `keyword_top10_count_yahoo` int(11) DEFAULT '0',
  `keyword_top3_count_bing` int(11) DEFAULT '0',
  `keyword_top3_count_yahoo` int(11) DEFAULT '0',
  `keyword_top1_count_bing` int(11) DEFAULT '0',
  `keyword_top1_count_yahoo` int(11) DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `own_domain_id` (`own_domain_id`),
  KEY `domain_own_domain_id_log_date` (`domain`,`own_domain_id`,`log_date`),
  KEY `own_domain_id_log_date` (`own_domain_id`,`log_date`)
) ENGINE=InnoDB AUTO_INCREMENT=680592051 DEFAULT CHARSET=utf8
1 row in set (0.09 sec)
4

2 に答える 2

2

ブランドン・ムーアが言ったように

クエリ自体は非常に単純なので、変更して高速化するためにできることは何もないと思います。

それでも、これを試して、少し違いがあるかどうかを確認できます

select `log_date`
from `top_competitor_summary_entity`
where
  own_domain_id = 4
  and keyword_top1_count > 0
  and (grouptag_id = 0 OR grouptag_id is null)
Order by log_date
LIMIT 0,1;
于 2012-12-27T11:12:39.417 に答える
1

クエリ自体は非常に単純なので、変更して高速化するためにできることは何もないと思います。それでも、「IsNull(grouptag_id、0)= 0」を使用しても、なんらかの違いが生じるかどうかは気になります。私はそれを疑っていますが、それが何かを削っているかどうかを見るのは楽しいかもしれません。

本当の問題は、own_domain_idの値が4であるレコードがおそらく大量にあり、where句の他のフィールドのインデックスがないことだと思います。それらに個別のインデックスを作成するか、このクエリに合わせて特別に調整されたインデックスを作成する場合は、参照される4つのフィールドすべてにキーを設定するインデックスを作成します。

他のいくつかの観察:

null値を処理するようにコードを変更する可能性がある場合(おそらくそれらを0として扱うだけ)、ほとんどのフィールドに配置しているデフォルト値を削除して、代わりにnullにすることができます。多くのフィールドの値が実際に0である場合、これはあまり効果がありませんが、多くのフィールドが0に設定されている場合、テーブルがディスク上で占めるスペースが少なくなり、スキャンにかかる時間が短くなります。テーブル。

テーブルを水平または垂直に分割することもできます。

水平方向:すべてのtop1フィールドを取得してtop1テーブルに配置し、すべてのtop3フィールドを取得してtop3テーブルに配置するなどの方法があります。または、すべてのyahooを1つのテーブルに、すべてのbingを別のテーブルに配置することもできます。または、あるテーブルのすべてのカウントフィールドと、別のテーブルのすべての検索フィールド。通常、一度に1セットのフィールドしか必要としない場合は、検索時間が短縮されますが、通常、ほとんどのクエリですべてのフィールドを取得することになった場合は、もちろん実際には役に立ちません。

垂直方向:これはおそらく価値があるよりもはるかに多くの作業ですが、テーブル内のレコードを複数のテーブルに分割し、それらを複数のハードディスクに配置して、すべて同時に非同期でクエリを実行できます。グーグルがこれらの線に沿って何かをするかどうか私はいつも疑問に思いました。

また、4バイトしかないintだけではなく、8バイトのidにbigintを使用していることにも気づきました。ある時点で数十億のレコードを現実的に処理すると思われる場合は、明らかにbigintが最適ですが、それ以外の場合は、データベースを約100メガバイト縮小できます。これにより、検索がわずかに高速化されます。そして、今それをintにして、必要になったときに後でbigintに戻すことができない理由はありません。

于 2012-12-27T11:06:24.483 に答える