2012-08-28 19 views
5

मेरे तालिकाPHP MySQL पृष्ठांकन मेज है कि धीमी गति से

Field Type Null Key Default Extra 
id  int(11)  NO PRI NULL auto_increment 
userid int(11)  NO MUL NULL  
title varchar(50) YES  NULL  
hosting varchar(10) YES  NULL  
zipcode varchar(5) YES  NULL  
lat  varchar(20) YES  NULL  
long varchar(20) YES  NULL  
msg varchar(1000)YES MUL NULL  
time datetime NO  NULL  

है। मैंने डेटा की 500k पंक्तियों को अनुकरण किया है और 500k की ऑटो वृद्धि के साथ केवल 230k छोड़ने के लिए यादृच्छिक रूप से 270k पंक्तियों को हटा दिया है।

यहाँ मेरी indexs

Keyname Type Unique Packed Field Cardinality Collation Null 
PRIMARY BTREE Yes No id   232377 A  
info BTREE No No userid   2003 A  
lat         25819 A YES 
long         25819 A YES 
title         25819 A YES 
time         25819 A 
इसे ध्यान में रखते

कर रहे हैं, यहाँ मेरी क्वेरी है:

चुनें * posts से कहां long> -११८.१३९०२८०२८८६ और long < -११८.०८१३०७९७११४ और lat> ३३.७९९८७१९७११४ और lat < 33.85759202886 आईडी एएससी लिमिटेड द्वारा आदेश 0, 25

दिखा पंक्तियों 0 - 15 (16 कुल, क्वेरी ले लिया 1.5655 सेकंड) [आईडी: 32846 - 540342]

क्वेरी केवल मुझे 1 पृष्ठ लाया, लेकिन यह अभी भी 1.5 सेकंड ले लिया है क्योंकि यह सब 230k रिकॉर्ड खोज करने के लिए किया था । यहां तक ​​कि अगर मैं का उपयोग जहां केवल वापस पाने के 16 परिणामों के लिए खंड मैं अभी भी एक धीमी गति से क्वेरी मिल

id select_type table type possible_keys key  key_len ref rows Extra 
1 SIMPLE  posts index NULL   PRIMARY 4  NULL 25  Using where 

तो:

क्वेरी समझाया है।

अब उदाहरण के लिए अगर मैं एक व्यापक खोज करते हैं:

SELECT * FROM `posts` WHERE `long`>-118.2544681443 AND `long`<-117.9658678557 AND `lat`>33.6844318557 AND `lat`<33.9730321443 ORDER BY id ASC LIMIT 0, 25 

दिखा पंक्तियों 0 - 24 (कुल 25, क्वेरी ले लिया .0849 सेकंड) [आईडी: 691 - 29818]

यह बहुत तेजी से होता है जब 20 पृष्ठों और 483 से बाहर पहले पृष्ठ को पुन: प्राप्त कुल पाया, लेकिन मैं 25

को सीमित लेकिन अगर मैं अंतिम पृष्ठ

SELECT * FROM `posts` WHERE `long`>-118.2544681443 AND `long`<-117.9658678557 AND `lat`>33.6844318557 AND `lat`<33.9730321443 ORDER BY id ASC LIMIT 475, 25 
के लिए पूछना

पंक्तियां दिखा रहा है 0 - 7 (8 कुल, क्वेरी 1.5874 सेकंड लिया गया) [आईडी: 5531 9 8 - 55 9 5 9 3]

मुझे धीमी क्वेरी मिलती है।

मेरा सवाल है कि मैं अच्छी अंकन कैसे प्राप्त करूं? जब वेबसाइट लाइव हो जाती है तो मुझे उम्मीद है कि जब यह बंद हो जाएगा तो उन पदों को हटा दिया जाएगा और सैकड़ों द्वारा दैनिक बनाया जाएगा। पदों को आईडी या टाइमस्टैम्प द्वारा आदेश दिया जाना चाहिए और आईडी अनुक्रमिक नहीं है क्योंकि कुछ रिकॉर्ड हटा दिए जाएंगे। मैं एक मानक पृष्ठांकन के लिए अपने परिणामों को रिकॉर्ड से

1 2 3 4 5 6 7 8 ... [Last Page] 
+0

क्या आप स्टोरेज इंजन और इंडेक्स के बारे में जानकारी जोड़ सकते हैं? –

+0

मैंने प्रत्येक कॉलम को अनुक्रमित किया है। और यह मैसूर इंजन है। – c3cris

+1

@CrisG क्या आप इस प्रश्न पर एक बक्षीस चाहते हैं? eggyal का जवाब बहुत अच्छा लग रहा है, लेकिन आपने टिप्पणी में अपने अंतिम प्रश्न का कभी जवाब नहीं दिया। यदि आप इसे उत्तर देने की आवश्यकता है (मैं एक उपहार के लिए खुला है) तो मैं इस पर आपके लिए एक बक्षीस लगाने के इच्छुक हूं। – Matt

उत्तर

0

मैं इसे समझ से बाहर केवल पंक्तियों को पार करना होगा। मुझे धीमा कर रहा था क्या आदेश है। चूंकि मैं एक सीमा कहूंगा और आगे की ओर जाने के लिए मैंने इसे और अधिक जाने के लिए कहा था। तो फिर मैं यह पहली बार डेटा मैं WERE खंड के साथ चाहते हैं निकालने के लिए एक सबक्वेरी जोड़कर तय तो मैं ORDER BY और LIMIT

SELECT * FROM 
    (SELECT * from `posts` as `p` 
     WHERE 
      `p`.`long`>-119.2544681443 
      AND `p`.`long`<-117.9658678557 
      AND `p`.`lat`>32.6844318557 A 
      ND `p`.`lat`<34.9730321443 

    ) as posttable 
    order by id desc 
    limit x,n 

इस्तेमाल किया कर रही है कि मैं निम्नलिखित हासिल द्वारा:

id select_type  table  type possible_keys key key_len ref  rows Extra 
1 PRIMARY   <derived2> ALL NULL   NULL NULL NULL 3031 Using filesort 
2 DERIVED   p   ALL NULL   NULL NULL NULL 232377 Using where 

अब मैं फ़िल्टर कर 232k परिणाम "कहां" और केवल ऑर्डरबाय का उपयोग करते हैं और 3031 परिणामों को सीमित करते हैं।

पंक्तियां दिखा रहा है 0 - 3030 (3,031 कुल, प्रश्न 0 ले लिया।1431 सेकेंड)

2

फ़िल्टर जो एक WHERE खंड का उपयोग करके पहले पन्नों पर छपी हैं: तो आप एक ऑफसेट, केवल एक पंक्ति संख्या निर्दिष्ट करने की आवश्यकता नहीं है। उदाहरण के लिए, आईडी या टाइमस्टैम्प के साथ केवल उन रिकॉर्ड्स के लिए देखी गई अंतिम आईडी या टाइमस्टैम्प का ट्रैक रखें और फ़िल्टर करें।

+0

+1। – Fluffeh

+0

मैंने उस समाधान को देखा है लेकिन यह केवल मुझे अगले पृष्ठ या पिछले होने की अनुमति देता है। – c3cris

+0

@ क्रिसग: डेटा कितना स्थिर है? – eggyal

0

दुर्भाग्यवश mysql को आपके 200 परिणामों को आउटपुट करने से पहले सभी 20000 पंक्तियों को [और पहले क्रमबद्ध] पढ़ना होगा। यदि आप WHERE क्लॉज के भीतर अनुक्रमित कॉलम पर फ़िल्टरिंग का उपयोग करके अपनी खोज को कम करने का प्रयास कर सकते हैं।

0

कुछ टिप्पणियां।

यह देखते हुए कि आप order by id देखते हैं, इसका मतलब है कि प्रत्येक पृष्ठ पर आपके पास पहले और आखिरी रिकॉर्ड के लिए आईडी है, इसलिए 200000 की सीमा के बजाय, आपको आईडी> $ last_id सीमा 20 का उपयोग करना चाहिए और यह तेज तेज होगा।

दोष यह स्पष्ट रूप से है कि यदि आप अनुक्रमिक नहीं हैं (बीच में हटाए गए हैं) तो आप "अंतिम" पृष्ठ या किसी भी पृष्ठ की पेशकश नहीं कर सकते हैं। फिर आप अंतिम ज्ञात आईडी और ऑफसेट + सीमा संयोजन के संयोजन का उपयोग कर सकते हैं।

और जाहिर है, उचित इंडेक्स होने से सॉर्टिंग और सीमित करने में भी मदद मिलेगी।

0

ऐसा लगता है कि आपके पास केवल प्राथमिक कुंजी अनुक्रमणिका है। आप इस तरह के रूप में क्षेत्रों का उपयोग करें, पर एक सूचकांक निर्धारित कर सकते हैं:

create index idx_posts_id on posts (`id` ASC); 
create index idx_posts_id_timestamp on posts (`id` ASC, `timestamp` ASC); 

अपने प्रमुख मैदान पर एक नियमित रूप से सूचकांक होने, अपनी प्राथमिक अद्वितीय कुंजी सूचकांक के अलावा, आमतौर पर mysql, द्वारा, बहुत तेजी लाने में मदद करता है।

0

Mysql के साथ काफी प्रदर्शन का एक सा खो देता है एक बड़े ऑफसेट: से mysqlPerformance blog:

सॉर्ट करने के लिए यदि आप पहली कुछ पंक्तियों की जरूरत है कुशल है इंडेक्स का उपयोग करके बड़े LIMIT में सावधान रहें, भले ही कुछ अतिरिक्त छानने तो आप जगह लेता है इंडेक्स द्वारा अधिक पंक्तियों को स्कैन करने की आवश्यकता है, फिर LIMIT द्वारा अनुरोध किया गया है। हालांकि यदि आप बड़ी ऑफसेट दक्षता के साथ LIMIT क्वेरी से निपट रहे हैं तो भुगतना होगा। LIMIT 1000,10 LIMIT 0,10 से धीमा होने की संभावना है। यह सच है कि अधिकांश उपयोगकर्ता परिणाम में 10 से अधिक पेज नहीं जाएंगे, हालांकि सर्च इंजन बॉट्स बहुत अच्छा कर सकते हैं। मैंने अपनी परियोजनाओं में 200+ पेज को देखकर बॉट देखे हैं। इसके अलावा देखभाल करने में असफल होने वाली कई वेबसाइटों के लिए एक डॉस अटैक लॉन्च करने के लिए बहुत आसान कार्य प्रदान करता है - कुछ कनेक्शन से कुछ बड़ी संख्या के साथ अनुरोध पृष्ठ और यह पर्याप्त है। यदि आप कुछ और नहीं करते हैं तो सुनिश्चित करें कि आप बहुत बड़े पेज नंबरों के साथ अनुरोध अवरुद्ध करते हैं।

कुछ मामलों के लिए, उदाहरण के लिए यदि परिणाम स्थैतिक हैं तो परिणाम को प्रीकंप्यूट करने का अर्थ हो सकता है ताकि आप उन्हें पदों के लिए पूछ सकें। तो आप LIMIT 1000,10 साथ क्वेरी के बजाय आप होगा जहां 1000 और 1009 है जो किसी भी स्थिति के लिए एक ही क्षमता है (जब तक यह अनुक्रमित की गई है) के बीच स्थिति

+0

हाँ, लेकिन यदि पोस्ट हटा दिए जाते हैं और आपकी लापता 1005-1007 .. और आप 10 चाहते हैं ... आपको केवल 7 परिणाम ही प्राप्त होंगे। – c3cris

0

आप उपयोग कर रहे हैं ऑटो वेतन वृद्धि आप उपयोग कर सकते हैं:

SELECT * FROM पदों WHERE आईडी >= 200000 ORDER BY आईडी DESC LIMIT 200000 , 30

इस तरह mysql ऊपर 200000.

+0

कोई भी संभव नहीं है क्योंकि पंक्तियां हटाई जा सकती हैं। – c3cris

+0

लेकिन यदि पंक्तियां हटा दी जाती हैं, तो भी ऑटो वृद्धि काउंटर कभी नीचे नहीं जाता है! उदाहरण के लिए – codefreak

+0

: '1 ------ रिकॉर्ड एक ---------- विवरण 2 -------- रिकॉर्ड बी ---------- विवरण बी' यदि रिकॉर्ड 2 हटा दिया गया है और एक नया रिकॉर्ड डाला गया है तो डेटा होगा: '1 ------ रिकॉर्ड एक ---------- विवरण 3 ------- -रेकॉर्ड सी ---------- विस्तार सी' – codefreak

संबंधित मुद्दे