MySQL için bir sql sorgusu hızlandırmak?

5 Cevap php

Benim mysql veritabanındaki tüm ülkeler, devletler ve şehirler içeren, geonames veritabanı var.

o nereden geldiğini kullanıcı seçmek öylesine i basamaklı bir menü oluşturmak için kullanıyorum: ülke -> Devlet -> ilçe -> şehir.

ancak asıl sorun sorgu bu tablodaki tüm 7 milyon satır i yoluyla çocukların satırların listesini almak istiyorum her zaman arar, ve bu bir süre 10-15 saniye alıyor olmasıdır.

i bu hızlandırmak nasıl acaba: önbelleğe? tablo görünümlerini? nasılsa Tablo yapısını yeniden düzenlemek?

ve en önemlisi, ben bunları nasıl yapacağız? Bana link verebilecek iyi dersler var?

i tüm yardım ve geri bildirim bu sorunu ele akıllı yollarını tartışırken takdir!

GÜNCELLEME: burada benim tablo yapısı:

CREATE TABLE `geonames_copy` (
  `geoname_id` mediumint(9) NOT NULL,
  `parent_id` mediumint(9) DEFAULT NULL,
  `name` varchar(200) DEFAULT NULL,
  `ascii_name` varchar(200) DEFAULT NULL,
  `alternate_names` varchar(4000) DEFAULT NULL,
  `latitude` decimal(10,7) DEFAULT NULL,
  `longitude` decimal(10,7) DEFAULT NULL,
  `feature_class` char(1) DEFAULT NULL,
  `feature_code` varchar(10) DEFAULT NULL,
  `country_code` varchar(2) DEFAULT NULL,
  `cc2` varchar(60) DEFAULT NULL,
  `admin1_code` varchar(20) DEFAULT NULL,
  `admin2_code` varchar(80) DEFAULT NULL,
  `admin3_code` varchar(20) DEFAULT NULL,
  `admin4_code` varchar(20) DEFAULT NULL,
  `population` bigint(20) DEFAULT NULL,
  `elevation` int(11) DEFAULT NULL,
  `gtopo30` smallint(6) DEFAULT NULL,
  `time_zone` varchar(40) DEFAULT NULL,
  `modification_date` date DEFAULT NULL,
  PRIMARY KEY (`geoname_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

ve burada sql sorgu:

            $query = "SELECT geoname_id, name
                    FROM geonames
                    WHERE parent_id = '$geoname_id'
                    AND (feature_class = 'A')";

parent_id ve feature_class: ben sadece 2 sütun için bir dizin oluşturmanız gerekir?

bir soru: yerine mysql kullanarak Solr ile bir dizin oluşturmak için daha iyi değil mi? bir yararı im zaten SOLR kullanarak ve başka bir tam metin arama destekler olmasıdır. belki bu yüzden (en iyi olmak için 2 şey) SOLR ve mysql hem dont kullanmak daha iyi?

5 Cevap

Belirtildiği gibi, daha fazla bilgi yardımcı (SQL, veritabanı yapısı) olacaktır.

Ayrıca ajax olmadan bu yapabilirdi ama AJAX öneri, iyi bir tanesidir.

Tüm verileri seçer herhangi bir noktada bir seçin yürütmek yapmayın. Bu son derece yavaş olacaktır.

Birincisi, ülkelerin tek listesini doldurmak. Kullanıcı bu listeden bir seçim yapmak için izin verin. Kullanıcı AJAX, veya tüm sayfayı yenileyerek ya, bir ülkeyi seçtikten sonra, sadece o ülke için devletlerin listesini doldurmak - gibi bir şey (ülke = @ ülke geonames itibaren devlet seçin). Kullanıcı bir devlet seçtiğinde, o ülke ve devlet için ilçe listesini doldurmak - (ülke = @ ülke ve devlet = @ devlet geonames itibaren ülkeyi seçin) gibi bir şey. Şehir için bu şekilde devam edin.

Ben MySQL ile çok aşina değilim, ama SqlServer ben sorguları bu seti hızlandırmak için (Ülke, Devlet, İlçe, Şehir) bir dizin yaratacak. Ben MySql bu dizin ya da değil sorguları tüm set hızlandırmak mümkün olacaktır emin değilim.

Tabii ki, ben veri burada yapılandırılmıştır hakkında bazı varsayımlar yapıyorum, böylece bu bilgi ya da ilgili olabilir veya olmayabilir.

Daha iyi bir cevap için, ama genel olarak SQL yayınlayın:

  • Eğer / wheres üzerinde birleştiği yapmak alanlarda dizinleri olun.
  • "SELECT *" kullanmayın etmeyin - sadece ihtiyacınız alanları seçin.
  • Dizilerin yerine nesneleri olarak hidrat.

Ayrıca, menü değiştirir asla eğer, bir dosyada HTML önbelleğe. Hatta sadece onlar sık ​​sık değiştirirseniz, sonra AJAX şehirler getirme, ülke / devlet HTML önbelleğe olabilir.

Ben bu gibi şeyler genellikle AJAX ile yapılır inanıyoruz. Başlangıçta, sadece ülke isimleri yüklemek ve bir seçildikten sonra, dinamik bundan sonra her alt bölümü için tekrarlayın sonra, bu ülkede devlet isimleri yükleyin.

Bu bir tablo bölümleme ve hatta alt bölümleri olan için iyi bir senaryodur. Sen devlet Ülkelere göre tablo bölümü, ve daha sonra alt-bölümleme olabilir. Bu önemli ölçüde sorgu yürütme planı çıkarılabilir veri olarak büyük kesimleri yoluyla aramak zorunda olacak veri miktarını azaltacaktır.

Here MySQL bölümleme hakkında bilgi için başlamak için iyi bir yerdir.

Bölümleme (ve hatta bölüm değil seçerseniz) ile birlikte, bu daha sorguların performansını artıracaktır olarak sütunları senin arama dizinleri oluşturmak isteyeceksiniz.

Here dizinleri oluşturmak için NASIL üzerine MySQL dokümantasyon, ama gerçekten dizinleri yapma konusunda zor yanı ne endeksine bilmektir. Genellikle sizin sorgu veya üzerinde JOIN sütunlarda WHERE yan tümceleri göstermek sütunları hedef olacak. Bu oldukça genel ve size (ve birçok durumda olmamalıdır) kütüğü her sütunu yok senin nerede cümlecikleri, ama bu başlangıç ​​için iyi bir yerdir. Soruda verilen sınırlı verilere dayanarak, büyük olasılıkla şehirlerin seçimini hızlandırmak amacıyla ülkeye ve bölgeye bir bileşik endeks isteyeceksiniz. Sen bir dizin gerekli olduğunu ve olmadığını aslında sorgu tarafından kullanılan edilirken belirlemek amacıyla planını açıklamak kullanmak isteyeceksiniz. "MySQL indeksleme" Yani bir arama yapmak ve yeterli bilgi daha bulacaksınız zaman, indeksleme tabloları nerede ve how.

Zaten değil varsa, bu veri normalleştirmek için yardımcı olacaktır. Örneğin, tablo şu gibi bir şey görünüyor:

usa;fl;miami;....
usa;fl;orlando;....

Bu gibi bir şey için değiştirilmesi gerekir:

COUNTRY Table:
--------------
COUNTRY_KEY            1
THREE_LETTER           'usa'
COUNTRY_NAME           'united states'
..OTHER COLUMNS....

REGION Table:
--------------
COUNTRY_KEY            1
REGION_KEY             10
REGION_CODE            'fl'
REGION_NAME            'florida'
..OTHER COLUMNS....

CITY Table:
--------------
REGION_KEY             10
CITY_KEY               20
CITY_NAME              'miami'
LAT                    123.12
LONG                   123.12
..OTHER COLUMNS----

UI açısından bakıldığında, sen sadece gerekli verileri yerleştirmek ve ardından eşleşen kriterleri ile diğer veri giriş noktalarını üreten konum bir şekilde bunu yazmak isteyeceksiniz. Yani ilk yük, bir ile ülke giriş doldurmak olacak:

SELECT country_key, three_letter 
FROM COUNTRY 
ORDER BY three_letter;

Kullanıcı ilgi duydukları ülkeyi seçtiğinde, o zaman o ülke anahtarı ile bütün bölgeleri dışarı seçin.

SELECT region_key, region_code 
FROM REGION WHERE country_key = :input_country_key 
ORDER BY region_code;

Yani üzerinde ve benzeri size kullanıcıların veri almak kadar.

Umarım bu yardımcı olur.

ALTER TABLE geonames_copy ADD INDEX (parent_id, feature_class);

hile yapmak gerekir. Sadece parent_id üzerinde bir dizin muhtemelen de iyi çalışır.