2017-04-07 22 views
0

私はテーブルuser_notificationを持っています。 Send_fail、2-キュー、3-成功(このような)SQLクエリを最適化する方法

テーブルで一日指数関数的に増加している〜100Kレコードの周りにある -

SELECT * FROM `user_notification` `t` WHERE `t`.`status`=2; 
ステータス1が

を実行するcronコマンドの実行があります日ごとに。このクエリは時間がかかりすぎています。このクエリを最適化する方法はありますか?

#Table structure for table `user_notification` 

CREATE TABLE `user_notification` (
    `id` int(11) NOT NULL, 
    `user_id` int(11) NOT NULL, 
    `notification_id` int(11) NOT NULL, 
    `notification_title` varchar(256) NOT NULL, 
    `notification_message` text NOT NULL, 
    `status` int(1) NOT NULL, 
    `created` int(11) NOT NULL, 
    `updated` int(11) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

ALTER TABLE `user_notification` 
    ADD PRIMARY KEY (`id`), 
    ADD KEY `user_id` (`user_id`), 
    ADD KEY `notification_id` (`notification_id`); 
ALTER TABLE `user_notification` 
    MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=94322; 
ALTER TABLE `user_notification` 
    ADD CONSTRAINT `user_notification_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`), 
    ADD CONSTRAINT `user_notification_ibfk_2` FOREIGN KEY (`notification_id`) REFERENCES `notification` (`id`); 


# Query_time: 0.010663 Lock_time: 0.000045 Rows_sent: 0 Rows_examined: 17294 
SET timestamp=1491527264; 
SELECT * FROM `user_notification` `t` WHERE `t`.`status`=2; 
+1

クエリの実行には0.01秒かかっています。これは悪いことではありませんが、依然として列ステータスで索引を作成できます。 –

+0

@Manishなぜあなたのクエリに 'tを使用していますか?SELECT * FROM user_notification t WHERE t.status = 2;'私は別名を使う必要はないと思う。 – user3441151

+2

@ user3441151 。 。エイリアスは一般的には良い考えであり、落胆してはいけません。 –

答えて

0

クエリはわずか0.01秒で実行されていますが、かなり高速です。とにかくそれを最適化したいなら、あなたができることがいくつかあります。まず、毎回8列すべてが必要ですか?代わりに、あなたは常にあなたが実際に必要なフィールドだけを一覧表示する必要があります

SELECT * 
FROM user_notification t 
WHERE t.status=2; 

を使用する:

それ以外
SELECT user_id, notification_id, notification_title, notification_message, status /*change columns as needed*/ 
FROM user_notification t 
WHERE t.status=2; 

、クエリのフィルタリングをスピードアップするために、列のステータスのためのインデックスを作成することができます。

ALTER TABLE user_notification 
CREATE NONCLUSTERED INDEX i1 ON user_notification (status); 
0

インデックスを作成するstatusで問題を解決する必要があります。

1

他にも言及したように、status列にインデックスを作成すると役立ちます。

これは、ますます巨大なテーブルの比較的小さな行(つまり、「キュー」行)で頻繁に作業するように思えます。 "キューに入れられた"レコードを自分のテーブルに入れ、ステータスが "成功"または "失敗"に変わったときに履歴テーブルに移動することを検討するとよいでしょう。そうすれば、あなたは比較的小さなテーブルからのみクエリしています。もちろん、この戦略には余分な削除と挿入が含まれているため、アプリケーションの動作に応じて他の問題が発生する可能性があります。

0

「キューに入れないでください。」

MySQLが優れたキューイングシステムを作っていると考えるのはよくある間違いです。

アイテムのエンキューとデキューの手間が、単にタスクを実行するための努力と近似している場合は、そうしてください。

OK、OK、あなたはキューを持っていると主張していますか?それから、Jerradが示唆するようにします。あるいは、「完了するのを待っている」というものがある余分なテーブルを持っているだけかもしれません。

何かをポーリングするときは、トランザクション上の問題に注意してください。そうしないと、2つのスレッドが同じアイテムを取得して作業する可能性があります。

なぜ0.01sのクエリがslowlogに表示されたのですか?おそらくlog_queries_not_using_indexesをオンにしました。 (私はその設定が事実上役に立たないと思うので、遅いログに混乱するだけです。)