1

現在、data_article_key_termsテーブルに約900,000のエントリがあり、キー用語をそれぞれの記事に関連付けています。目標は、任意の日付範囲を選択し、その日付範囲の記事に基づいて上位15の主要な用語を表示できるようにすることです。

私が実行している問題は、実行しているクエリに6秒近くかかることですが、それよりも高速である必要があります。これは、実行しているシステムに基づいた相対的なものであり、より強力なマシンを使用できることを認識していますが、そのルートに進む前に、可能な限り最適化しようとしています。

データの整合性を維持するために、MySQLストレージエンジンとしてInnoDBを使用しています。私が理解しているように、MyISAMはcount(*)を使用すると高速になりますが、そのエンジンを使用することもできません。

また、固定された時間範囲に基づいてキータームカウントをテーブルに保存することも検討しましたが、それは保存および追跡するための大量のデータになってしまいます。

この体験を最適化する方法について誰かが良い提案をしていますか?

私は次のテーブルを持っています:

このテーブルには、記事情報が格納されています。

CREATE TABLE `data_article` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `connection_id` int(11) NOT NULL,
  `folder_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `uid` varchar(100) NOT NULL,
  `date` date NOT NULL,
  `influencer_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `data_article_5930b15a` (`connection_id`),
  KEY `data_article_4e5f642` (`folder_id`),
  KEY `data_article_fbfc09f1` (`user_id`),
  KEY `data_article_43ae76a1` (`influencer_id`),
  KEY `data_article_date` (`date`),
  CONSTRAINT `connection_id_refs_id_b2ae9152` FOREIGN KEY (`connection_id`) REFERENCES `account_connection` (`id`),
  CONSTRAINT `folder_id_refs_id_e343586a` FOREIGN KEY (`folder_id`) REFERENCES `account_folder` (`id`),
  CONSTRAINT `influencer_id_refs_id_45cd3615` FOREIGN KEY (`influencer_id`) REFERENCES `data_influencer` (`id`),
  CONSTRAINT `user_id_refs_id_aca13cc9` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`)
)

このテーブルには、重要な用語が格納されています。

CREATE TABLE `data_keyterm` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `term` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `data_keyterm_term` (`term`)
)

このテーブルには、記事と重要な用語の関係が格納されています。

CREATE TABLE `data_article_key_terms` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `article_id` int(11) NOT NULL,
  `keyterm_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `article_id` (`article_id`,`keyterm_id`),
  KEY `data_article_key_terms_30525a19` (`article_id`),
  KEY `data_article_key_terms_1d848ca4` (`keyterm_id`),
  CONSTRAINT `article_id_refs_id_d87be8f5` FOREIGN KEY (`article_id`) REFERENCES `data_article` (`id`),
  CONSTRAINT `keyterm_id_refs_id_50d233f8` FOREIGN KEY (`keyterm_id`) REFERENCES `data_keyterm` (`id`)
)

このテーブルには、記事に関連付けられているインフルエンサーが格納されています。

CREATE TABLE `data_influencer` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `title` varchar(100) NOT NULL,
  `email` varchar(100) NOT NULL,
  `active` tinyint(1) NOT NULL,
  `user_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `data_influencer_fbfc09f1` (`user_id`),
  KEY `data_influencer_name` (`name`),
  CONSTRAINT `user_id_refs_id_b1bb5d4f` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`)
)

これは、時間範囲に基づいてキーワードをプルし、グループ化し、頻度順に並べ替えるために使用しているSQLステートメントです。

SELECT dk.id, dk.term as term, COUNT(dk.id) as count
FROM data_keyterm dk
INNER JOIN data_article_key_terms dakt ON dakt.keyterm_id = dk.id
INNER JOIN data_article da ON da.id = dakt.article_id
INNER JOIN data_influencer di ON di.id = da.influencer_id
WHERE da.user_id = 1
AND da.date between '2010-08-07' AND '2012-08-07'
AND di.active = True
GROUP BY dk.id
ORDER BY count DESC
LIMIT 15;
4

2 に答える 2

0

900,000 レコードと 3 つの内部結合を持つテーブルで内部結合を実行すると、実行に時間がかかります。すぐに結果を得るには、solar などの外部検索エンジンを試してみるとよいと思います。

于 2012-08-07T14:58:38.303 に答える
0

この場合、インデックスが役に立たないのではないかと思います。クエリの選択性は? つまり、いくつの記事/キーの組み合わせが使用されていますか?

パフォーマンスを最適化するには、クエリ プランでユーザー ID と日付によって記事を選択し、結合を行う必要があると思います。そして、この縮小されたサブセットを追加の結合に使用します。代わりに、全体でインデックスを使用していると思われます。

私の最初の提案は、article テーブルの userid/date の 2 つのインデックスを 1 つのインデックスに置き換えることです。WHERE 句は、この単一のインデックスを使用して条件を満たすことができます。これにより、クエリ プランが簡素化され、改善される場合があります。

テストするもう 1 つのことは、アーティクル/キー テーブルを少し非正規化することです。キーと記事が同時に作成されると仮定して、ユーザー ID と日付をこのテーブルに追加します。次に、クエリをこのテーブルの制限として言い換えるだけです。その後、ユーザー ID と日付に複合インデックスを作成できます。ただし、これらのフィールドに個別のインデックスを作成することはお勧めしません。

于 2012-08-07T16:06:12.593 に答える