MySQL Yavaş üzerinde katılın.

9 Cevap php

Ben 2 tablolar var. 1 müzik ve 2. listenTrack olduğunu. listenTrack her şarkının benzersiz oyunlarını izler. Ben ayın popüler şarkılar için sonuçlar almak için çalışıyorum. Ben sonuç alıyorum ama onlar sadece çok uzun alıyor. Aşağıda benim tablolar ve sorgu

430.000 satırlar

CREATE TABLE `listentrack` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `sessionId` varchar(50) NOT NULL,
    `url` varchar(50) NOT NULL,
    `date_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    `ip` varchar(150) NOT NULL,
    `user_id` int(11) DEFAULT NULL,
     PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=731306 DEFAULT CHARSET=utf8

12500 satırlar

CREATE TABLE `music` (
   `music_id` int(11) NOT NULL AUTO_INCREMENT,
   `user_id` int(11) NOT NULL,
   `title` varchar(50) DEFAULT NULL,
   `artist` varchar(50) DEFAULT NULL,
   `description` varchar(255) DEFAULT NULL,
   `genre` int(4) DEFAULT NULL,
   `file` varchar(255) NOT NULL,
   `url` varchar(50) NOT NULL,
   `allow_download` int(2) NOT NULL DEFAULT '1',
   `plays` bigint(20) NOT NULL,
   `downloads` bigint(20) NOT NULL,
   `faved` bigint(20) NOT NULL,
   `dateadded` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
   PRIMARY KEY (`music_id`)
) ENGINE=MyISAM AUTO_INCREMENT=15146 DEFAULT CHARSET=utf8


SELECT COUNT(listenTrack.url) AS total, listenTrack.url 
FROM listenTrack
LEFT JOIN music ON music.url = listenTrack.url
WHERE DATEDIFF(DATE(date_created),'2009-08-15') = 0
GROUP BY listenTrack.url
ORDER BY total DESC
LIMIT 0,10

Bu sorgu çok karmaşık değil ve satırları çok büyük değil, ben sanmıyorum.

Bu hızlandırmak için herhangi bir yolu var mı? Ya da daha iyi bir çözüm önerebilir? Bu, her ayın uzaklaştırmak bir cron işi olacak ama aynı zamanda gün sonuçlarına göre yapmak istiyorum.

Oh btw i çalıştırmak için 4 dakika boyunca, bu yerel çalıştırıyorum, ama eşya üzerinde yaklaşık 45 saniye sürer

9 Cevap

Ben bir SQL Server adam daha değilim ancak bu kavramlar başvurmalıdır.

Ben dizinleri eklemek istiyorum:

  1. ListenTrack üzerine, url ile bir dizin eklemek ve DATE_CREATED
  2. Müzik, url ile bir dizin eklemek

Bu indeksler (- son düzenleme sabit ben aslen kadar karışık tablo adlarını vardı) müthiş sorgu hızlandırmak gerekir.

Çoğunlukla size endeksi de bir JOIN kullanılan herhangi bir sütun gerekir. Senin durumunda, gereken dizin hem listentrack.url ve music.url

@ Jeff s - MySQL bu sütunun üzerinde bir dizin kullanamazsınız nedenle ilk bir fonksiyonu sayesinde bu çalışan çünkü bir dizin yardımcı olmaz music.date_created. Endeksli başvurulan sütun statik gibi kullanılır, böylece Genellikle, bir sorgu yazabilirsiniz:

DATEDIFF(DATE(date_created),'2009-08-15') = 0

olur

date_created >= '2009-08-15' and date_created < '2009-08-15'

Bu 2009-08-15 vardır ve o sütundaki herhangi indeksler aday olmasına izin kayıtları aşağı süzer. MySQL bu indeksi KULLANMAYIN olabileceğini unutmayın, bu diğer faktörlere bağlıdır.

Your best bet is to make a dual index on listentrack(url, date_created) and then another index on music.url

Bu 2 indeksler bu özel sorgu kapsayacaktır.

Not Eğer ORDER BY yapmak için diskte geçici bir tabloya kayıtları yazmak zorundadır, çünkü EXPLAIN bu sorguyu hala bir using filesort almak için gidiyoruz çalıştırırsanız.

Genel olarak her zaman MySQL sorgu yürütmek ve sonra oradan gidecek nasıl bir fikir almak için EXPLAIN altında sorgu çalıştırmalısınız. EXPLAIN belgelerine bakın:

http://dev.mysql.com/doc/refman/5.0/en/using-explain.html

Katılmak yardımcı olacak bir dizin oluşturma deneyin:

CREATE INDEX idx_url ON music (url);

Ben daha önce belirgin kaçırmış olabileceğini düşünüyorum. Neden tüm müzik tablo katılıyor? Sen de tüm bu tablodaki verileri kullanıyor ve sağ, bir sol gerekli değildir katılabileceği performans görünmüyor? Ben sorguda olan bu tablo çok daha yavaş olacağını düşünüyorum ve herhangi bir değer katmak olmaz. Url dahil gerekli olmadığı sürece, eşleşen değeri olmayan bir satırı dahil zorlamak katılmak hakkını gerekir bu durumda, müzik üzerinden tüm başvuruları alır.


I would add new indexes, as the others mention. Specifically I would add: music url listentrack date_created,url

Bu senin bir ton katılacak artıracaktır.

Sonra sorgu bakmak istiyorsunuz, tablonun her satırı üzerinde çalışmayı gerçekleştirmek için sistemini zorluyor. Bu bir dizi olarak tarih sınırlaması ifadeleri için daha iyi olurdu.

Not sure of the syntax off the top of my head: where '2009-08-15 00:00:00' <= date_created < 2009-08-16 00:00:00

İşte bu hızla uygun kayıtları bulmak için dizin kullanmak için izin vermelidir. Müzik Birleştirilen iki anahtar indeksi tarihi ve URL tabanlı kayıtları bulmak için izin vermelidir. Onların endeksinde DATE_CREATED diğer yönde url, gidiş daha iyi olabilir, deneme gerekir.

Bu sorgu için açıklamak planı hem sağ sütunda "dizini kullanarak" demeliyim. İşte bu toplamları hesaplamak için tablodaki verileri vurmak zorunda anlamına gelir.

Ben de MySQL için yapılandırılmış olan bellek ayarlarını kontrol ederim. Eğer yeteri kadar bellek tahsis yok gibi geliyor. Sunucu tabanlı ayarları ve konu bazlı ayarları arasındaki farklar hakkında çok dikkatli olun. Bir 10MB önbelleği ile sunucu 10MB önbellek ile bir iplik hızlı bellek bir sürü kullanabilirsiniz, oldukça küçük.

Jacob

Neden iki tabloda url tekrarlıyor?

Yerine music_id tutun ve bu konuda katılmak listentrack var. Metin arama yanı sıra ekstra endeksi kurtulur.

Ayrıca, belki daha doğru. Belirli bir parça değil url dinledi olduğu kez izliyoruz. Ne url değişiklikler olur?

Ön-gruplama ve sonra MySQL / MyISAM ile çok daha hızlı yapar şeyler katılmadan. (Ben bu az diğer DB ile gerekli şüpheli değilim)

Bu kadar hızlı olmayan katıldı sürümü hakkında yapmalıdır:

SELECT
   total, a.url, title
FROM
(
  SELECT COUNT(*) as total, url
  from listenTrack
  WHERE DATEDIFF(DATE(date_created),'2009-08-15') = 0
  GROUP BY url
  ORDER BY total DESC
  LIMIT 0,10
) as a
LEFT JOIN music ON music.url = a.url
;

P.S. - Yerine url bir kimliği ile iki tablo arasında eşleme sağlıklı bir tavsiye.

Dizinleri ekledikten sonra, o zaman matematik işlemleri daha hızlı hale getirecek bir UNIX_TIMESTAMP olmaya date_created için yeni bir sütun ekleyerek keşfetmek isteyebilirsiniz.

Eğer belirli bir tarihte güncellendi tüm satırlar arıyoruz göründüğü gibi olsa fark işlevi var ben neden emin değilim.

Bunu bir hata var gibi görünüyor gibi sorgu bakmak isteyebilirsiniz.

Ünite testleri kullanıyorsanız o zaman sizin sorgusu ve bunun yerine bir unix zaman damgası kullanılarak bir sorgunun sonuçlarını karşılaştırabilirsiniz.

Her iki tablo url alanına bir dizin eklemek isteyebilirsiniz.

i aynı sorgular ve aynı veritabanı yapıları ile, SQL Server 2008 için mysql dönüştürüldüğünde, sorguları hızlı büyüklük 1-3 emir koştu, söyledi sahip.

ben bunun bazı rdbms (mysql optimize ... çok iyi değil) ve bunun bazı nasıl rdbms rezerv sistem kaynakları ile yapmak zorunda olabilir ile ilgisi olduğunu düşünüyorum. her ne kadar, karşılaştırmalar sadece db çalışır üretim sistemlerinde yapılmıştır.

Aşağıda Bu muhtemelen sorguyu hızlandırmak için çalışmaya devam eder.

CREATE INDEX music_url_index ON music (url) USING BTREE; CREATE INDEX listenTrack_url_index ON listenTrack (url) USING BTREE;

Eğer gerçekten oluyor karşılaştırmalar ve satır taramaların toplam sayısını bilmek gerekir. Nasıl burada koduna bu cevap bir görünüm elde etmek için olduğunu açıklamak kullanarak http://www.siteconsortium.com/h/p1.php?id=mysql002.