MySQL Sub Select Sorgu Optimizasyonu

2 Cevap php

Ben istatistikleri derlemek için günlük bir sorgu koşuyorum - ama gerçekten verimsiz gibi görünüyor. Bu Query:

SELECT a.id, tstamp, label_id, (SELECT author_id FROM b WHERE b.tid = a.id ORDER BY b.tstamp DESC LIMIT 1) AS author_id
FROM a, b
WHERE (status = '2' OR status = '3') 
AND category != 6
AND a.id = b.tid
AND (b.type = 'C' OR b.type = 'R')
AND a.tstamp1 BETWEEN {$timestamp_start} AND {$timestamp_end}
ORDER BY b.tstamp DESC
LIMIT 500

Bu sorgu gerçekten yavaş çalıştırmak gibi görünüyor. Adlandırma bok için özür dilemek - Ben gerçek tablo isimlerini açıklamıyoruz istendi.

Dış seçin tablo a gelen bir satır alır ve masa b bir satır alır çünkü seçme bir alt var nedenidir. Ama aynı zamanda b tablodan son author_id bilmeniz gerekir, bu yüzden bunu birini döndürmek için subselect çalıştırın. Ben bir php döngü içinde başka bir select çalıştırmak istemiyorum - bu da verimsiz olduğu gibi.

Düzgün çalışır - Ben sadece bu veri seti almanın çok daha hızlı bir yol bulmak gerekir.

2 Cevap

b.tstamp b.tid içinde benzersiz ise, OMG Ponies 'çözüm almak.

Aksi takdirde bu çözümü deneyebilirsiniz. Bu b.tstamp DESC tarafından tüm sonuç sıralar ve bir sıraya göre ekler author_id. Dış seçer en tstamp başına olan biri olan, rank = 1 sadece satır alır author_id.

SELECT id, tstamp, label_id, author_id
  FROM (SELECT id,
               tstamp,
               label_id,
               author_id,
               CASE
                 WHEN @author_id != author_id THEN @row_num := 1 
                 ELSE @row_num := @row_num + 1
               END AS rank,
               @author_id := b.author_id
          FROM a,
               b,
               (SELECT @row_num := 0, @author_id := NULL) y
          WHERE a.id = b.tid
          AND (status = '2' OR status = '3') 
          AND category != 6
          AND (b.type = 'C' OR b.type = 'R')
          AND a.tstamp1 BETWEEN {$timestamp_start} AND {$timestamp_end}
          ORDER BY b.author_id, b.tstamp DESC
  ) x
 WHERE x.rank = 1
LIMIT 500

Ben denedim, bu yüzden işe yaramazsa yorum lütfen değil.

Deneyin:

  SELECT a.id,
         b.tstamp,
         label_id,
         y.author_id
    FROM TABLE_A a
    JOIN TABLE_B b ON b.tid = a.id
    JOIN (SELECT b.tid,
                 MAX(b.tstamp) 'm_tstamp'
            FROM TABLE_B b
        GROUP BY b.tid) x ON x.tid = a.id
    JOIN (SELECT b.tid,
                 b.author_id,
                 b.tstamp
            FROM TABLE_B b
        GROUP BY b.tid) y ON y.tid = a.id
                         AND y.tstamp = x.m_tstamp
   WHERE status IN ('2', '3')
     AND b.type IN ('C', 'R')
     AND category != 6
     AND a.tstamp1 BETWEEN {$timestamp_start} AND {$timestamp_end}
ORDER BY b.tstamp DESC 
   LIMIT 500