2015-04-19 22 views
5

endeksler olmadan seçme sorgusu ile karşılaştırıldığında MySQL Güncelleme katılmak Aynı ipin ardışık sıraları arasındaki zaman farkı.son derece yavaş olarak bazı sunucu günlükleri yakalar 100k satırlarla MySQL tablo oluşturduk

Ancak
SELECT * FROM logs AS a 
LEFT JOIN (
    SELECT id, 
     from_unixtime(@diff) AS starttime, 
     date AS endtime, 
     IF(@diff = 0, 0, (unix_timestamp(date) - @diff)/60) AS session_time1, 
     @diff := unix_timestamp(date) 
    FROM logs, 
     (SELECT @diff := 0) AS x 
    ORDER BY ip, logs.date 
) AS b ON 
    a.id = b.id 

, bir önceki sorguyu kullanmaya çalıştığınızda zaman oturumu güncellemek için güncelleme birleşim, aşağıdaki güncelleştirme sorgusu: Ben bir saniyeden kısa sürer aşağıdaki seçme sorgusu ile ulaşmak mümkün duyuyorum 600 saniyeden fazla zaman alır:

UPDATE logs AS a 
LEFT JOIN (
    SELECT id, 
     from_unixtime(@diff) AS starttime, 
     date AS endtime, 
     IF(@diff = 0, 0, (unix_timestamp(date) - @diff)/60) AS session_time1, 
     @diff := unix_timestamp(date) 
    FROM logs, 
     (SELECT @diff := 0) AS x 
    ORDER BY ip, logs.date 
) AS b ON 
    a.id = b.id 
SET session_time = session_time1; 

Neyi eksik?

Teşekkürler!

GÜNCELLEME: İşteselect arasında EXPLAIN geçerli:

+----+-------------+------------+--------+---------------+------+--------+ 
| id | select_type | table | type | possible_keys | key | rows | 
+----+-------------+------------+--------+---------------+------+--------+ 
| 1 | PRIMARY  | a   | ALL | NULL   | NULL | 109029 | 
| 1 | PRIMARY  | <derived2> | ALL | NULL   | NULL | 108680 | 
| 2 | DERIVED  | <derived3> | system | NULL   | NULL | 1  | 
| 2 | DERIVED  | logs  | ALL | NULL   | NULL | 109029 | 
| 3 | DERIVED  | NULL  | NULL | NULL   | NULL | NULL | 
+----+-------------+------------+--------+---------------+------+--------+ 
+1

'WHERE ip = '...''? 100k girişlerin tümünü güncellediğinizi, ancak seçtiğinizleri ("LEFT JOIN' = ilk gruptaki seçim kurallarına uymayan öğeler) güncellediğinizi görüyorsunuz. INNER JOIN' kullanmayı dene? –

+0

Teşekkürler Alejandro, ama yorumunuzu tam olarak anlamıyorum. İç katılma neden daha iyi olur? 'Where' cümlesiyle ne demek istiyorsun? – kahlo

+0

Üzgünüm, daha iyi açıklamalıydım. "UPDATE" kullandığınızda, hangi verilerin güncellenmesi gerektiğini filtrelemek için genellikle bir "WHERE" ifadesi kullanırsınız. Durumunuzda, belirli bir IP adresi için güncellemek istediğinizde, 'WHERE ip = ''' sadece o belirli IP ile verileri işlemek için daha iyi olmalıdır (sorgunuzun tablonuzdaki her kaydı işlediğini düşünüyorum) hepsi olmasa bile, güncellenir). –

cevap

0

Başlat dışarı session_time tüm satırlara NULL olmak. iki şekilde sorguyu değiştirin: Eğer bir kapanış saati yoksa

  • NULL için Set session_time
  • (sonunda) GÜNCELLEME WHERE session_time IS NULL ekle, başka doğru ayarlayın.

İlk gece, şimdiki saat kadar yavaş olacak, ancak bundan sonra çok daha hızlı olacak çünkü "yeni" satırlardan yalnızca birkaç tanesi üzerinde çalışacak.

düzenleme

(genellikle) bir JOIN ihtiyaçları, ON maddesi. logs ve a'un ile logs arasındaki bağlantıya bağlanma. EXPLAIN, logs ve a 109K * 108K kombinasyonlarından geçmesi gerektiğini göstermektedir; sadece 109K olmalı. İhtiyaç duyulmadıkça, 'u da kaldırın.

+0

Teşekkürler Rick, önerinizi ekledim. Bununla birlikte, bu sorgu zaten bir günde (sadece günde 100k satır) oluşturulan yeni bilgileri içerir. Hala böyle bir zaman farkına neden olan ve onu düzelten şey hakkında meraktayım. – kahlo

+0

5.6 çalışıyorsanız, lütfen 'EXPLAIN SELECT ...' ve 'EXPLAIN UPDATE ...' seçeneklerini gönderin. Belki de bu optimizatörün aralarında farklı bir şey yaptığını gösterecektir. –

+0

Sadece EXPLAIN SELECT ... 'i ekledim ama sürüm 5.5.29 ve önceki 5.6.3 sürümlerini çalıştırdığım için 'EXPLAN UPDATE ...' ekleyemem. – kahlo

İlgili konular