2

700,000 の mysql クエリをループせずにデータセットを収集する方法を見つけようとしています。

私は2つのテーブルを持っています

users

id autoincrement, 
time timestamp, 
username varchar(200), 
email varchar(100), 
ip varchar(20)

そしてuniq_ip_

ip unique varchar(20), 
most_recent datetime, 
count (int)

usersには 2,500 万行あり、ユーザーがサイトで作業する際のアクティビティを記録します。uniq_ipすべての IP 番号のリストと、それがユーザーにリストされた回数 (トリガー更新時) があります。

現時点では、空想のコーディング中に、すべての IP のリストを取得し、uniq_ipそれらをループして、それらの IP ごとに最新の 2000 レコードを取得しています。700,000 行あるためuniq_ip、このループは非常に厄介で、合計 700,000 件のクエリが発生します。

select * from users where ip = '$outerloopip' order by `time` desc limit 2000;

各 IP の最新の 2000 件のリストを取得する単一のクエリを取得しようとしています。1.2.3.4 が 10,000 回リストされている場合、時間フィールドに基づいて最新の 2000 年が必要です。

1つのクエリでそれを行う方法はありますか?

4

2 に答える 2

1

以前の回答について申し訳ありませんが、更新されたクエリを再読して適用しました。最近の 2000 個の IP アドレスだけが必要だと思っていました。とにかく、これはすべての IP アドレスを処理し、IP ごとの合計レコードを 2,000 エントリに制限し、最新のものを一番上に置きます。インデックスがあることを確認します

(IP,TIME DESC)

次に、このクエリを試してください。明確にするのを逃した重要なこと。HAVING 句は、group-by または order-by 句の後に適用されます。そのため、データは IP アドレスと日付/時刻の降順の適切な順序で事前に返され、@sql 変数が適用されます。レコードが修飾され、最終的な結果セットに追加する準備ができたら、HAVING 句が適用されます。その時点で、シーケンス カウンターを見て、... 2000 より大きい場合は破棄して、次のレコードに移動します。

私の最初のクエリによると、すべてを保存してから、2 度目の循環を行い、2000 を超えるものを追い出していました。これがおそらく、ディスク容量を吹き飛ばしていた理由です。

select
      U.*,
      @LastSeq := IF( @LastIP = U.IP, @LastSeq +1, 1 ) as IPSequence,
      @LastIP := U.IP as carryForNextRecord
   from 
      ( select @LastIP := '', @LastSeq := 0 ) sqlvars,
      Users U
   order by
      U.IP,
      U.time DESC
   having 
      IPSequence <= 2000
于 2012-04-29T01:06:19.130 に答える
0
SELECT ip as IP ,
     (SELECT GROUP_CONCAT(time)     FROM users WHERE ip = IP ORDER BY time DESC LIMIT 2000) as Time,
     (SELECT GROUP_CONCAT(username) FROM users WHERE ip = IP ORDER BY time DESC LIMIT 2000) as UserName,
     (SELECT GROUP_CONCAT(email)    FROM users WHERE ip = IP ORDER BY time DESC LIMIT 2000) as Email
FROM uniq_id
于 2012-05-04T13:20:25.920 に答える