veri göndermek çok uzun sürüyor mysql


9

Milyonlarca kayıt (14.000.000) ile basit bir tablo var ve basit bir sorgu için "veri gönderme" çok fazla zaman harcıyor.

Tablo

CREATE TABLE IF NOT EXISTS details (
  id int(11) NOT NULL,
  date date NOT NULL,
  time int(2) NOT NULL,
  minutes_online decimal(5,0) NOT NULL,
  minutes_playing decimal(5,0) NOT NULL,
  minutes_chatting decimal(5,0) NOT NULL,
  minutes_away decimal(5,0) NOT NULL
  PRIMARY KEY (id,date,time)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

Basit sorgu

mysql> SELECT * FROM details WHERE id = 3014595;

Açıklamak

mysql> EXPLAIN SELECT * FROM details WHERE id = 3014595;
+----+-------------+-----------+------+---------------+---------+---------+-------+------+-------+
| id | select_type | table     | type | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-----------+------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | details   | ref  | PRIMARY       | PRIMARY | 4       | const | 1482 |       |
+----+-------------+-----------+------+---------------+---------+---------+-------+------+-------+

Sorgu profili

mysql> SHOW PROFILE FOR QUERY 1;
+--------------------------------+----------+
| Status                         | Duration |
+--------------------------------+----------+
| starting                       | 0.000024 |
| checking query cache for query | 0.000078 |
| checking permissions           | 0.000014 |
| Opening tables                 | 0.000126 |
| System lock                    | 0.000011 |
| Table lock                     | 0.000030 |
| init                           | 0.000027 |
| optimizing                     | 0.000117 |
| statistics                     | 0.040077 |
| preparing                      | 0.000029 |
| executing                      | 0.000006 |
| Sending data                   | 7.536960 |
| end                            | 0.000013 |
| query end                      | 0.000004 |
| freeing items                  | 0.000037 |
| storing result in query cache  | 0.000006 |
| logging slow query             | 0.000003 |
| cleaning up                    | 0.000006 |
+--------------------------------+----------+

Gördüğünüz gibi, SELECTifade dizini kullandı ve sadece 1482 satırı okudu. Ancak, sorgu verileri göndermek için 7.536960 saniye harcadı. Sorgu çok daha fazla satır okumak gibi.

Basit bir sorgu, sadece 7 alan (satır avg 59 Bayt) ve fantezi fonksiyonu ile. Buna neyin sebep olabileceği hakkında bir fikrin var mı?

Not: id, kullanıcı kimliğidir. Her kullanıcının, her günün her saati için en az bir girişi olabilir. Bu nedenle, id benzersiz değildir.

Düzenleme: Aynı yapıya ve çok daha fazla satıra (34 Milyon) sahip başka bir tablo var. Aynı sorguyu bu daha büyük tabloda çalıştırırsam, sonuçları 1 saniyeden daha kısa sürede döndürür.

Tek fark, daha büyük tablo, daha küçük tablo kadar sorgu almaz.

  • Sorgu sayısının süreci yavaşlatması mümkün mü? MySQL önbelleği açık. Ben de sorgu sayısını azaltmak için sorguları önbelleğe CakePHP ettik.
  • Tablonun kaydedildiği dosyanın bozuk veya başka bir şey olması mümkün mü?

Güncelleme Sorun, veri katmanını web katmanından ayırarak çözüldü. Veri katmanı da RAM'de bir yükseltme aldı ve raid10 üzerinde çalışıyor.


SELECTDönüş kaç satır ?
hjpotter92

1591 rows in set (16.48 sec)Sorguyu tekrar çalıştırdım, bu yüzden süre farklı. Şimdi aldı 16 saniye (!!)
rlcabral

* kullanmak yerine sütunları kullanmayı deneyin ve sonra ne fark yarattığını görün
Muhammad Raheel

Hayır! Aynı sonuç.
rlcabral

Kimlik sütununu basit bir birincil dizin yapmaya çalışın. Kimlik benzersiz bir alan olduğundan, onunla karmaşık dizinler oluşturmanıza gerek yoktur. Bu, bir ışık hızı gibi birincil anahtarla aramanızı hızlı hale getirmelidir.
Alexander Pravdin

Yanıtlar:


1

Bu soruya rastlayan ve RAM'i yükseltmeden bile merak eden herkes için veri göndermenin neden bu kadar uzun sürdüğünü merak edenler için. Bunun nedeni, veri gönderme işleminin gönderilecek veriyi arama süresini içermesidir.

https://dev.mysql.com/doc/refman/5.7/en/general-thread-states.html

İş parçacığı bir SELECT deyimi için satırları okuyup işliyor ve istemciye veri gönderiyor. Bu durum sırasında gerçekleşen işlemler büyük miktarda disk erişimi (okuma) gerçekleştirme eğiliminde olduğundan, genellikle belirli bir sorgunun ömrü boyunca en uzun süre çalışan durumdur.


-2

En İyileştir tablo tablenini kullanarak tabloyu optimize etmeyi deneyin ve durumu kontrol edin.

Büyük Değişikliklerin Yapılması Gerekiyor:

Alter table tablename engine = 'INNODB'

Bu size çok yardımcı olacaktır ve muhtemelen tabloda bir birincil anahtar olmalıdır, ancak birincil anahtar olarak üç sütun eklediniz.


-3

Kimlik için ayrı bir dizin oluşturun:

tablo ayrıntılarını değiştirme d1 (id) anahtarını ekleyin;

Bu dizini yürürlüğe koymak için MySQL veya

tablo detaylarını analiz etmek;

Mümkünse, işlem desteği ve diğer avantajlar için veritabanını InnoDB olarak da değiştirebilirsiniz.


Bu nasıl yardımcı olacak?
Colin 't Hart
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.