stat表 字段 uid,act,time
我想取出每个uid最近的一个act
我现在的sql:
select * from (select * from stat order by uid,time desc) a group by uid
这个表数据量比较大,查起来有点慢,有没有更好的办法
甚至这个:
select act,count(*) num from (select * from (select * from stat order by uid,time desc) a group by uid) b group by act
表:
CREATE TABLE `stat` (
`uid` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
`act` bigint(20) NOT NULL,
`time` bigint(20) DEFAULT NULL,
PRIMARY KEY (`uid`,`act`),
KEY `index_time` (`time`) USING BTREE,
KEY `index_act` (`act`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
最初に私の意見を述べさせていただきます。間違いがあれば修正してください。
まず質問者のSQL文は間違っていると思いますが、group byを実行するのはデータベースの実装機構に依存しているだけなので結果は正しいと思われます。たとえば、並べ替え順序を変更すると、結果は間違ったものになります。
group byを使用した後、サブジェクトがクエリできるフィールドは、データベースがAfterに準拠しているため、集計関数またはgroup byのフィールドのいずれかになります。 uid がグループ化されると、act フィールドと time フィールドの値のセットがランダムに選択されます。質問のSQLは正常に動作しているようです。ソート後、データベースはデフォルトで最もソートされたものを選択するはずです。
正しい SQL は次のようになると思います。
まず、グループ内の各人の最新の実行時間をクエリし、uid と時間に基づいて完全な操作情報を取得します。
対象のデータベースにインデックス付きの uid がある場合でも、この SQL のクエリ効率は許容できるはずです。
ちょっと個人的な意見です。
元のベースにいくつかの変更を加えたところ、ローカル テストのパフォーマンスがわずかに向上しました。ローカル テスト データは 30,000 セットです。
クエリ条件の列にインデックス、B 番号インデックス、B+ 番号インデックスなどを作成してみてください。
作成方法の詳細については、Baidu で検索できます。
このステートメントにネストされたサブクエリが必要なのはなぜですか? 1 つのステートメントで実行できないのでしょうか? ロジックはあまり明確ではありませんが、通常の状況ではクエリ情報を出力するために Explain を使用します。
グループ化は 1 つで十分ですが、なぜ 2 つのレイヤーを記述する必要があるのですか