2010-06-30 6 views
9

मेरे पास एक SQL क्वेरी है जो जटिल क्वेरी के लिए परिणामों की संख्या की गणना करता है। 20 परिणाम तक सीमित होने पर वास्तविक चयन क्वेरी बहुत तेज होती है, लेकिन अनुकूलन के बाद मेरे वर्तमान टेबल पर गिनती संस्करण लगभग 4.5 सेकंड लेता है।7-टेबल-ट्यून कैसे करें MySQL गिनती क्वेरी में जहां टेबल 30,000+ पंक्तियां हैं?

यदि मैं दो जोड़ों को हटा देता हूं और साइट टैग और गैलरी टैग पर क्लॉज कहता है, तो क्वेरी 1.5 सेकंड पर होती है। यदि मैं 3 अलग-अलग प्रश्न बनाते हैं - एक भुगतान साइट का चयन करने के लिए, एक नाम चुनने के लिए और एक को सबकुछ खींचने के लिए - मैं क्वेरी को 6 सेकंड तक प्राप्त कर सकता हूं, जो अभी भी पर्याप्त नहीं है। यह मुझे एक संग्रहीत प्रक्रिया का उपयोग करने के लिए भी मजबूर करेगा क्योंकि मुझे हाइबरनेट में कुल 4 प्रश्न बनाना होगा।

क्वेरी यहां "जैसा है", के लिए कुछ जानकारी है:

Handler_read_key 1,746,669
Handler_read_next 1546324

गैलरी तालिका 40,000 पंक्तियों
है है साइट तालिका 900 पंक्तियों
है नाम तालिका 800 पंक्तियों
है टैग तालिका 3560 पंक्तियों

मैं MySQL और ट्यूनिंग, और मैं एच के सुंदर नया हूँ है पर एवेन्यू अनुक्रमित:

  • 'शब्द' टैग तालिका में कॉलम
  • 'प्रकाशित' नाम तालिका के लिए गैलरी तालिका
  • 'मान' में स्तंभ

मैं करने के लिए देख रहा हूँ इस क्वेरी को 0.1 मिलीसेकंड पर प्राप्त करें।

SELECT count(distinct gallery.id) 
from gallery gallery 
    inner join 
     site site 
      on gallery.site_id = site.id 
    inner join 
     site_to_tag p2t 
      on site.id = p2t.site_id 
    inner join 
     tag site_tag 
      on p2t.tag_id = site_tag.id 
    inner join 
     gallery_to_name g2mn 
      on gallery.id = g2mn.gallery_id 
    inner join 
     name name 
      on g2mn.name_id = name.id 
    inner join 
     gallery_to_tag g2t 
      on gallery.id = g2t.gallery_id 
    inner join 
     tag tag 
      on g2t.tag_id = tag.id 
where 
    gallery.published = true and (
     name.value LIKE 'sometext%' or 
     tag.term = 'sometext' or 
     site.`name` like 'sometext%' or 
     site_tag.term = 'sometext' 
    ) 

के बारे में बताएं डाटा:

| id | select_type | table  | type | possible_keys              | key    | key_len | ref          | rows | Extra        | 
+----+-------------+--------------+--------+-------------------------------------------------------------------+--------------------+---------+-------------------------------------------+------+------------------------------------+ 
| 1 | SIMPLE  | site   | index | PRIMARY,nameIndex             | nameIndex   | 258  | NULL          | 950 | Using index; Using temporary  | 
| 1 | SIMPLE  | gallery  | ref | PRIMARY,publishedIndex,FKF44C775296EECE37,publishedSiteIdIndex | FKF44C775296EECE37 | 9  | production.site.id      | 20 | Using where      | 
| 1 | SIMPLE  | g2mn   | ref | PRIMARY,FK3EFFD7F8AFAD7A5E,FK3EFFD7F832C04188      | FK3EFFD7F8AFAD7A5E | 8  | production.gallery.id      | 1 | Using index; Distinct    | 
| 1 | SIMPLE  | name   | eq_ref | PRIMARY,valueIndex            | PRIMARY   | 8  | production.g2mn.name_id     | 1 | Distinct       | 
| 1 | SIMPLE  | g2t   | ref | PRIMARY,FK3DDB4D63AFAD7A5E,FK3DDB4D63E210FBA6      | FK3DDB4D63AFAD7A5E | 8  | production.g2mn.gallery_id    | 2 | Using where; Using index; Distinct | 
| 1 | SIMPLE  | tag   | eq_ref | PRIMARY,termIndex             | PRIMARY   | 8  | production.g2t.tag_id      | 1 | Distinct       | 
| 1 | SIMPLE  | p2t   | ref | PRIMARY,FK29424AB796EECE37,FK29424AB7E210FBA6      | PRIMARY   | 8  | production.gallery.site_id    | 3 | Using where; Using index; Distinct | 
| 1 | SIMPLE  | site_tag  | eq_ref | PRIMARY,termIndex             | PRIMARY   | 8  | production.p2t.tag_id      | 1 | Using where; Distinct    | 
+----+-------------+--------------+--------+-------------------------------------------------------------------+--------------------+---------+-------------------------------------------+------+------------------------------------+ 

व्यक्तिगत गणना गति:

[SQL] select count(*) from gallery; 
Affected rows: 0 
Time: 0.014ms 
Results: 40385 

[SQL] 
select count(*) from gallery_to_name; 
Affected rows: 0 
Time: 0.012ms 
Results: 35615 

[SQL] 
select count(*) from gallery_to_tag; 
Affected rows: 0 
Time: 0.055ms 
Results: 165104 

[SQL] 
select count(*) from tag; 
Affected rows: 0 
Time: 0.002ms 
Results: 3560  

[SQL] 
select count(*) from site; 
Affected rows: 0 
Time: 0.001ms 
Results: 901 

[SQL] 
select count(*) from site_to_tag; 
Affected rows: 0 
Time: 0.003ms 
Results: 7026 
+8

<0.1 मिलसेकंड बहुत कुछ पूछ रहा है। – RedFilter

+2

अपने प्रश्न के लिए EXPLAIN का आउटपुट जोड़ें। – Naktibalda

+0

ठीक है, डेटा समझाया गया। धन्यवाद – egervari

उत्तर

9

मैंने इस पोस्ट के अंत में परीक्षण डेटा तैयार करने के लिए अपनी टेस्ट स्कीमा और एक स्क्रिप्ट शामिल की है। मैंने MySQL को कैशिंग क्वेरी परिणामों से रोकने के लिए SQL_NO_CACHE विकल्प का उपयोग किया है - यह केवल परीक्षण के लिए है और अंत में हटा दिया जाना चाहिए।

यह डोनी द्वारा प्रस्तावित एक समान विचार है, लेकिन मैंने इसे थोड़ा सा बताया है। अगर मैं सही तरीके से शामिल हो गया हूं, तो प्रत्येक चयन में सभी शामिल होने की आवश्यकता नहीं है, क्योंकि प्रत्येक दूसरों से प्रभावी रूप से स्वतंत्र है। मूल WHERE खंड यह निर्धारित करता है कि gallery.published सत्य होना चाहिए और फिर OR द्वारा 4 स्थितियों की एक श्रृंखला के साथ अनुसरण किया जाना चाहिए। इसलिए प्रत्येक क्वेरी को अलग से निष्पादित किया जा सकता है। यहाँ चार मिलती हैं:

gallery <--> gallery_to_name <--> name 
gallery <--> gallery_to_tag <--> tag 
gallery <--> site 
gallery <--> site <--> site_to_tag <--> tag 

क्योंकि gallerysite_id होता है, इस मामले में, कोई जरूरत site तालिका के माध्यम से के लिए मध्यवर्ती में शामिल होने नहीं है। पिछले शामिल हो इसलिए इस को कम किया जा सकता है:

gallery <--> site_to_tag <--> tag 

अलग SELECT चल रहा है, और परिणाम गठबंधन करने के लिए UNION का उपयोग कर, बहुत तेजी से है। यहाँ परिणाम तालिका संरचनाओं और सूचियों को मान इस पोस्ट के अंत में दिखाया गया है:

SELECT SQL_NO_CACHE COUNT(id) AS matches FROM (
    (SELECT g.id 
    FROM gallery AS g 
    INNER JOIN site AS s ON s.id = g.site_id 
    WHERE g.published = TRUE AND s.name LIKE '3GRD%') 
UNION 
    (SELECT g.id 
    FROM gallery AS g 
    INNER JOIN gallery_to_name AS g2n ON g2n.gallery_id = g.id 
    INNER JOIN name AS n ON n.id = g2n.name_id 
    WHERE g.published = TRUE AND n.value LIKE '3GRD%') 
UNION 
    (SELECT g.id 
    FROM gallery AS g 
    INNER JOIN gallery_to_tag AS g2t ON g2t.gallery_id = g.id 
    INNER JOIN tag AS gt ON gt.id = g2t.tag_id 
    WHERE g.published = TRUE AND gt.term = '3GRD') 
UNION 
    (SELECT g.id 
    FROM gallery AS g 
    INNER JOIN site_to_tag AS s2t ON s2t.site_id = g.site_id 
    INNER JOIN tag AS st ON st.id = s2t.tag_id 
    WHERE g.published = TRUE AND st.term = '3GRD') 
) AS totals; 

+---------+ 
| matches | 
+---------+ 
|  99 | 
+---------+ 
1 row in set (0.00 sec) 

गति खोज मापदंड के आधार पर भिन्न होता है। निम्न उदाहरण में, एक अलग खोज मूल्य हर तालिका के लिए प्रयोग किया जाता है, और इस तरह के ऑपरेटर के रूप में वहाँ अब प्रत्येक के लिए कर रहे हैं और अधिक संभावित मैचों, एक छोटे से अधिक काम करने के लिए है:

SELECT SQL_NO_CACHE COUNT(id) AS matches FROM (
    (SELECT g.id 
    FROM gallery AS g 
    INNER JOIN site AS s ON s.id = g.site_id 
    WHERE g.published = TRUE AND s.name LIKE '3H%') 
UNION 
    (SELECT g.id 
    FROM gallery AS g 
    INNER JOIN gallery_to_name AS g2n ON g2n.gallery_id = g.id 
    INNER JOIN name AS n ON n.id = g2n.name_id 
    WHERE g.published = TRUE AND n.value LIKE '3G%') 
UNION 
    (SELECT g.id 
    FROM gallery AS g 
    INNER JOIN gallery_to_tag AS g2t ON g2t.gallery_id = g.id 
    INNER JOIN tag AS gt ON gt.id = g2t.tag_id 
    WHERE g.published = TRUE AND gt.term = '3IDP') 
UNION 
    (SELECT g.id 
    FROM gallery AS g 
    INNER JOIN site_to_tag AS s2t ON s2t.site_id = g.site_id 
    INNER JOIN tag AS st ON st.id = s2t.tag_id 
    WHERE g.published = TRUE AND st.term = '3OJX') 
) AS totals; 

+---------+ 
| matches | 
+---------+ 
| 12505 | 
+---------+ 
1 row in set (0.24 sec) 

इन परिणामों के साथ कृपापूर्वक तुलना एक प्रश्न है जो कई का उपयोग करता है मिलती है:

SELECT SQL_NO_CACHE COUNT(DISTINCT g.id) AS matches 
FROM gallery AS g 
INNER JOIN gallery_to_name AS g2n ON g2n.gallery_id = g.id 
INNER JOIN name   AS n ON n.id = g2n.name_id 
INNER JOIN gallery_to_tag AS g2t ON g2t.gallery_id = g.id 
INNER JOIN tag    AS gt ON gt.id = g2t.tag_id 
INNER JOIN site   AS s ON s.id = g.site_id 
INNER JOIN site_to_tag  AS s2t ON s2t.site_id = s.id 
INNER JOIN tag    AS st ON st.id = s2t.tag_id 
WHERE g.published = TRUE AND (
    gt.term = '3GRD' OR 
    st.term = '3GRD' OR 
    n.value LIKE '3GRD%' OR 
    s.name LIKE '3GRD%'); 

+---------+ 
| matches | 
+---------+ 
|  99 | 
+---------+ 
1 row in set (2.62 sec) 

SELECT SQL_NO_CACHE COUNT(DISTINCT g.id) AS matches 
FROM gallery AS g 
INNER JOIN gallery_to_name AS g2n ON g2n.gallery_id = g.id 
INNER JOIN name   AS n ON n.id = g2n.name_id 
INNER JOIN gallery_to_tag AS g2t ON g2t.gallery_id = g.id 
INNER JOIN tag    AS gt ON gt.id = g2t.tag_id 
INNER JOIN site   AS s ON s.id = g.site_id 
INNER JOIN site_to_tag  AS s2t ON s2t.site_id = s.id 
INNER JOIN tag    AS st ON st.id = s2t.tag_id 
WHERE g.published = TRUE AND (
    gt.term = '3IDP' OR 
    st.term = '3OJX' OR 
    n.value LIKE '3G%' OR 
    s.name LIKE '3H%'); 

+---------+ 
| matches | 
+---------+ 
| 12505 | 
+---------+ 
1 row in set (3.17 sec) 

SCHEMA
अनुक्रमित आईडी स्तंभों पर प्लस site.name, name.value और tag.term महत्वपूर्ण हैं:

DROP SCHEMA IF EXISTS `egervari`; 
CREATE SCHEMA IF NOT EXISTS `egervari`; 
USE `egervari`; 

-- ----------------------------------------------------- 
-- Table `site` 
-- ----------------------------------------------------- 

DROP TABLE IF EXISTS `site` ; 
CREATE TABLE IF NOT EXISTS `site` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT , 
    `name` VARCHAR(255) NOT NULL , 
    INDEX `name` (`name` ASC) , 
    PRIMARY KEY (`id`)) 
ENGINE = InnoDB; 

-- ----------------------------------------------------- 
-- Table `gallery` 
-- ----------------------------------------------------- 

DROP TABLE IF EXISTS `gallery` ; 
CREATE TABLE IF NOT EXISTS `gallery` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT , 
    `site_id` INT UNSIGNED NOT NULL , 
    `published` TINYINT(1) NOT NULL DEFAULT 0 , 
    PRIMARY KEY (`id`) , 
    INDEX `fk_gallery_site` (`site_id` ASC) , 
    CONSTRAINT `fk_gallery_site` 
    FOREIGN KEY (`site_id`) 
    REFERENCES `site` (`id`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE) 
ENGINE = InnoDB; 

-- ----------------------------------------------------- 
-- Table `name` 
-- ----------------------------------------------------- 

DROP TABLE IF EXISTS `name` ; 
CREATE TABLE IF NOT EXISTS `name` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT , 
    `value` VARCHAR(255) NOT NULL , 
    INDEX `value` (`value` ASC) , 
    PRIMARY KEY (`id`)) 
ENGINE = InnoDB; 

-- ----------------------------------------------------- 
-- Table `tag` 
-- ----------------------------------------------------- 

DROP TABLE IF EXISTS `tag` ; 
CREATE TABLE IF NOT EXISTS `tag` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT , 
    `term` VARCHAR(255) NOT NULL , 
    INDEX `term` (`term` ASC) , 
    PRIMARY KEY (`id`)) 
ENGINE = InnoDB; 

-- ----------------------------------------------------- 
-- Table `gallery_to_name` 
-- ----------------------------------------------------- 

DROP TABLE IF EXISTS `gallery_to_name` ; 
CREATE TABLE IF NOT EXISTS `gallery_to_name` (
    `gallery_id` INT UNSIGNED NOT NULL , 
    `name_id` INT UNSIGNED NOT NULL , 
    PRIMARY KEY (`gallery_id`, `name_id`) , 
    INDEX `fk_gallery_to_name_gallery` (`gallery_id` ASC) , 
    INDEX `fk_gallery_to_name_name` (`name_id` ASC) , 
    CONSTRAINT `fk_gallery_to_name_gallery` 
    FOREIGN KEY (`gallery_id`) 
    REFERENCES `gallery` (`id`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE, 
    CONSTRAINT `fk_gallery_to_name_name` 
    FOREIGN KEY (`name_id`) 
    REFERENCES `name` (`id`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE) 
ENGINE = InnoDB; 

-- ----------------------------------------------------- 
-- Table `gallery_to_tag` 
-- ----------------------------------------------------- 

DROP TABLE IF EXISTS `gallery_to_tag` ; 
CREATE TABLE IF NOT EXISTS `gallery_to_tag` (
    `gallery_id` INT UNSIGNED NOT NULL , 
    `tag_id` INT UNSIGNED NOT NULL , 
    PRIMARY KEY (`gallery_id`, `tag_id`) , 
    INDEX `fk_gallery_to_tag_gallery` (`gallery_id` ASC) , 
    INDEX `fk_gallery_to_tag_tag` (`tag_id` ASC) , 
    CONSTRAINT `fk_gallery_to_tag_gallery` 
    FOREIGN KEY (`gallery_id`) 
    REFERENCES `gallery` (`id`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE, 
    CONSTRAINT `fk_gallery_to_tag_tag` 
    FOREIGN KEY (`tag_id`) 
    REFERENCES `tag` (`id`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE) 
ENGINE = InnoDB; 

-- ----------------------------------------------------- 
-- Table `site_to_tag` 
-- ----------------------------------------------------- 

DROP TABLE IF EXISTS `site_to_tag` ; 
CREATE TABLE IF NOT EXISTS `site_to_tag` (
    `site_id` INT UNSIGNED NOT NULL , 
    `tag_id` INT UNSIGNED NOT NULL , 
    PRIMARY KEY (`site_id`, `tag_id`) , 
    INDEX `fk_site_to_tag_site` (`site_id` ASC) , 
    INDEX `fk_site_to_tag_tag` (`tag_id` ASC) , 
    CONSTRAINT `fk_site_to_tag_site` 
    FOREIGN KEY (`site_id`) 
    REFERENCES `site` (`id`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE, 
    CONSTRAINT `fk_site_to_tag_tag` 
    FOREIGN KEY (`tag_id`) 
    REFERENCES `tag` (`id`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE) 
ENGINE = InnoDB; 

परीक्षण डाटा
यह site 900 के साथ पंक्तियाँ, tag 3560 के साथ पंक्तियाँ, 800 पंक्तियों के साथ name और gallery 40,000 पंक्तियों के साथ भरता है, और लिंक तालिका में प्रविष्टियों सम्मिलित करता है:

DELIMITER // 
DROP PROCEDURE IF EXISTS populate// 
CREATE PROCEDURE populate() 
BEGIN 
    DECLARE i INT DEFAULT 0; 

    WHILE i < 900 DO 
     INSERT INTO site (name) VALUES (CONV(i + 1 * 10000, 20, 36)); 
     SET i = i + 1; 
    END WHILE; 

    SET i = 0; 
    WHILE i < 3560 DO 
     INSERT INTO tag (term) VALUES (CONV(i + 1 * 10000, 20, 36)); 
     INSERT INTO site_to_tag (site_id, tag_id) VALUES ((i MOD 900) + 1, i + 1); 
     SET i = i + 1; 
    END WHILE; 

    SET i = 0; 
    WHILE i < 800 DO 
     INSERT INTO name (value) VALUES (CONV(i + 1 * 10000, 20, 36)); 
     SET i = i + 1; 
    END WHILE; 

    SET i = 0; 
    WHILE i < 40000 DO  
     INSERT INTO gallery (site_id, published) VALUES ((i MOD 900) + 1, i MOD 2); 
     INSERT INTO gallery_to_name (gallery_id, name_id) VALUES (i + 1, (i MOD 800) + 1); 
     INSERT INTO gallery_to_tag (gallery_id, tag_id) VALUES (i + 1, (i MOD 3560) + 1); 
     SET i = i + 1; 
    END WHILE; 
END; 
// 
DELIMITER ; 
CALL populate(); 
1

गणना के रूप में वे की आवश्यकता होती है आदेश में सभी डेटा कर्सर द्वारा वापस प्राप्त करने में कठिनाई यह पता लगाने के लिए कितने पंक्तियों को अक्सर धीमी गति से कर रहे हैं वास्तव में लाया जाएगा।

प्रत्येक व्यक्तिगत टेबल पर गिनती करने में कितना समय लगता है? कुल समय जोड़ें - यदि यह 0.1 मिलीसेकंड से अधिक है तो मुझे नहीं लगता कि आप जितनी जल्दी चाहें निष्पादित करने के लिए क्वेरी प्राप्त कर पाएंगे। जहाँ तक यह लाने के लिए के रूप में तरीकों ऊपर जाता है, तो आप

select 
    count(distinct this_.id) as y0_ 
from 
    (select * from gallery where published=?) this_ 
inner join 
    site site3_ 
     on this_.site_id=site3_.id 
inner join 
    site_to_tag list7_ 
     on site3_.id=list7_.site_id 
inner join 
    tag sitetag4_ 
     on list7_.tag_id=sitetag4_.id 
inner join 
    gallery_to_name names9_ 
     on this_.id=names9_.gallery_id 
inner join 
    name name2_ 
     on names9_.name_id=name2_.id 
inner join 
    gallery_to_tag list11_ 
     on this_.id=list11_.gallery_id 
inner join 
    tag tag1_ 
    on list11_.tag_id=tag1_.id 
where lower(name2_.value) like ? or 
     tag1_.term=? or 
     lower(site3_.name) like ? or 
     lower(this_.description) like ? or 
     sitetag4_.term=? 

में, एक उप चयन में कहां खंड मानदंडों में से कुछ को आगे बढ़ाने के रूप में कितने क्षेत्रों इन तालिकाओं में से प्रत्येक पर कर रहे हैं की कोशिश कर सकते? क्या आप डेटाबेस को डेटा एकत्र करने की मात्रा को कम करने के लिए उप-चयन का उपयोग कर सकते हैं, या क्या आपको वास्तव में सभी कॉलम की आवश्यकता है?

तीन LIKE भविष्यवाणियों की उपस्थिति चीजों को धीमा करने जा रही है, जहां WHERE खंड में लोअर फ़ंक्शन का उपयोग किया जाएगा। यदि आपको केस-असंवेदनशील तुलना करने में सक्षम होना आवश्यक है तो दो फ़ील्ड, एक 'सामान्य' (टाइप किए गए) मामले में एक और बेहतर (या UPPER) मामले में संग्रहीत एक असंवेदनशील खोज करने के लिए बेहतर हो सकता है। आप 'सामान्य' केस संस्करण के साथ निचले/UPPER को सिंक में रखने के लिए ट्रिगर का उपयोग कर सकते हैं।

मुझे उम्मीद है कि इससे मदद मिलती है।

संपादित करें:

व्याख्या योजना उत्पादन यह है कि क्षेत्रों में किया प्रकट नहीं होता है को देखते हुए अपने कहां खंड अनुक्रमित रहे हैं - या कम से कम यह अनुक्रमित उपयोग नहीं किया जा रहा है प्रकट होता है। यह कहां से सभी या भविष्यवाणियों का उप-उत्पाद हो सकता है। यदि इन फ़ील्ड को अनुक्रमित नहीं किया गया है, तो आप उन्हें अनुक्रमणित करने का प्रयास कर सकते हैं।

+0

के दूसरी तरफ लागू नहीं होता है, धन्यवाद और प्रयास के लिए धन्यवाद प्रतिक्रिया में डाल दिया है। मैंने प्रकाशन के साथ उप-चयन करने की कोशिश की, और यह वास्तव में क्वेरी को थोड़ा अधिक समय लेता है :(मैंने उपरोक्त गणनाओं के समय पोस्ट किए हैं। – egervari

+0

मैंने देखा कि हाइबरनेट प्राथमिक कुंजी को कई से अधिक जोड़ों में नहीं डाल रहा था इसलिए गैलरी_to_name, gallery_to_tag और site_to_tag के मामलों में, कोई प्राथमिक कुंजी नहीं थी :(। मैंने प्राथमिक कुंजी जोड़ दी, और क्वेरी 9.5 सेकेंड से 5 सेकंड तक चली गई। क्या मुझे इन्हें इंडेक्स करने की आवश्यकता है? – egervari

+0

@egervari - अगर आपके पास पहले से इंडेक्स नहीं हैं, आप name.value, tag.term, site.name, और gallery.description को अनुक्रमणित करने का प्रयास कर सकते हैं। मुझे नहीं पता कि वे कितने उपयोगी होंगे लेकिन यह कोशिश करने के लिए कुछ है। –

1

ऐसा प्रतीत होता है अपने WHERE खंड अपराधी हो सकता है, विशेष रूप से निम्नलिखित:

lower(name2_.value) like ? 

अनुसार MySQL documentation रहे हैं:

डिफ़ॉल्ट वर्ण सेट और मिलान latin1 और latin1_swedish_ci हैं, इसलिए nonbinary स्ट्रिंग तुलना डिफ़ॉल्ट रूप से केस असंवेदनशील हैं।

आपको अपने WHERE खंड में लोअर() फ़ंक्शन की आवश्यकता नहीं हो सकती है। तुलना के बाईं तरफ के कार्य इंडेक्स के उपयोग को रोकते हैं।

आपके LIKE मूल्य कैसा दिखते हैं? यदि आप मूल्य के बाईं तरफ वाइल्डकार्ड का उपयोग कर रहे हैं, तो यह इंडेक्स के उपयोग को रोकता है।

UNION के साथ OR कथन का प्रयास करें।

DISTINCT के बिना क्वेरी को चलाने का प्रयास करें ताकि यह देखने के लिए कि यह आपकी क्वेरी को कितना प्रभावित कर रहा है।

+0

सभी को बदलना निचले()/जैसे कि सादा = (केवल इसके बिल्ली के लिए) के परिणामस्वरूप कुल क्वेरी समय की तुलना में बेहद मामूली प्रदर्शन लाभ होता है। यह लगभग 4 -5 सेकेंड बूस्ट है। यह है। मैंने पोस्ट करने से पहले पहली चीजों में से एक कोशिश की थी। यह स्पष्ट है इस पर समस्या नहीं है। – egervari

+0

@Egervari, कारण शायद यह अधिक मदद नहीं कर रहा है क्योंकि यह किसी भी तरह से name2_ पर इंडेक्स का उपयोग नहीं कर रहा है। यदि आपका LIKE क्लॉज अच्छा है, तो संभवतः, यह संयुक्त या क्लॉज है जो इसे प्रभावित कर रहा है। यूनियन पर स्विच करें। आपको क्वेरी में सुधार करने और इंडेक्स का उपयोग करने के लिए सभी बदलाव करना होगा। –

+5

@egervari, चीजों को परिप्रेक्ष्य में रखने के लिए, कि .4 -5s बचत कुल निष्पादन समय के लिए आपके लक्ष्य 40-50 गुणा है। – mikerobi

1

OR अच्छे इंडेक्स के साथ भी क्वेरी प्रदर्शन प्रदर्शन। टेबल खराब होने के कारण यह बदतर हो जाता है।

यह भयानक बदसूरत है, लेकिन यह तेजी से होने की संभावना है (स्पष्ट रूप से पठनीयता की कीमत पर)। यदि MySQL केवल सीटीई का समर्थन करता है तो यह बहुत अधिक, neater होगा।

आप एक छोटा बैच लिखने और एक अस्थायी क्वेरी के सामान्य भाग को एक अस्थायी तालिका में चुनने और फिर अस्थायी तालिका के विरुद्ध सब कुछ करने का भी चयन कर सकते हैं। अच्छी तरह से काम करने के लिए आपको temp तालिका को अनुक्रमणित करना पड़ सकता है या नहीं, यह वास्तव में पंक्ति गणनाओं पर निर्भर करता है।

(ध्यान दें कि union पहले से ही एक distinct करता है, तो इसे फिर से count एक और तरह करते हैं और मजबूर करने के लिए कोई आवश्यकता नहीं है)

select 
    count(id) 
from (
SELECT gallery.id 
from gallery gallery 
    inner join 
     site site 
      on gallery.site_id = site.id 
    inner join 
     site_to_tag p2t 
      on site.id = p2t.site_id 
    inner join 
     tag site_tag 
      on p2t.tag_id = site_tag.id 
    inner join 
     gallery_to_name g2mn 
      on gallery.id = g2mn.gallery_id 
    inner join 
     name name 
      on g2mn.name_id = name.id 
    inner join 
     gallery_to_tag g2t 
      on gallery.id = g2t.gallery_id 
    inner join 
     tag tag 
      on g2t.tag_id = tag.id 
where 
    gallery.published = true and name.value like 'sometext%' 
UNION 
SELECT gallery.id 
from gallery gallery 
    inner join 
     site site 
      on gallery.site_id = site.id 
    inner join 
     site_to_tag p2t 
      on site.id = p2t.site_id 
    inner join 
     tag site_tag 
      on p2t.tag_id = site_tag.id 
    inner join 
     gallery_to_name g2mn 
      on gallery.id = g2mn.gallery_id 
    inner join 
     name name 
      on g2mn.name_id = name.id 
    inner join 
     gallery_to_tag g2t 
      on gallery.id = g2t.gallery_id 
    inner join 
     tag tag 
      on g2t.tag_id = tag.id 
where 
    gallery.published = true and tag.term = 'sometext' 
UNION 
SELECT gallery.id 
from gallery gallery 
    inner join 
     site site 
      on gallery.site_id = site.id 
    inner join 
     site_to_tag p2t 
      on site.id = p2t.site_id 
    inner join 
     tag site_tag 
      on p2t.tag_id = site_tag.id 
    inner join 
     gallery_to_name g2mn 
      on gallery.id = g2mn.gallery_id 
    inner join 
     name name 
      on g2mn.name_id = name.id 
    inner join 
     gallery_to_tag g2t 
      on gallery.id = g2t.gallery_id 
    inner join 
     tag tag 
      on g2t.tag_id = tag.id 
where 
    gallery.published = true and site.`name` like 'sometext%' 
UNION 
SELECT gallery.id 
from gallery gallery 
    inner join 
     site site 
      on gallery.site_id = site.id 
    inner join 
     site_to_tag p2t 
      on site.id = p2t.site_id 
    inner join 
     tag site_tag 
      on p2t.tag_id = site_tag.id 
    inner join 
     gallery_to_name g2mn 
      on gallery.id = g2mn.gallery_id 
    inner join 
     name name 
      on g2mn.name_id = name.id 
    inner join 
     gallery_to_tag g2t 
      on gallery.id = g2t.gallery_id 
    inner join 
     tag tag 
      on g2t.tag_id = tag.id 
where 
    gallery.published = true and site_tag.term = 'sometext' 
) as x 
0

मैं मानता हूं मैं समय नहीं लिया पूरी तरह से अपने तालिकाओं को समझने के लिए और प्रश्नों। हालांकि, जिस तरह के प्रतिक्रिया समय के लिए आप पूछ रहे हैं, और वर्तमान सुझावों की स्पष्ट जटिलता के लिए, मैं कहूंगा कि यह उन स्थितियों में से एक है जहां (एसक्यूएल से उन सभी रिकॉर्ड्स को टैल करने के बजाय पूछना है जिन्हें मैं गिनना चाहता हूं) I हमेशा अद्यतित गणना की एक अलग तालिका रखें, और हमेशा किसी भी रिकॉर्ड जोड़ें/बदलें/हटाएं पर ट्रिगर कोड के साथ किसी उचित गणना को अपडेट करें।

उदाहरण के लिए, एक लाख पंक्तियों के साथ एक लेनदेन फ़ाइल की कल्पना करें, और मुझे कुल क्षेत्र 2 चाहिए। मैं डीबी से एसयूएम() क्षेत्र में पूछ सकता हूं, या मैं किसी तालिका में फ़ील्ड 2 के लिए अलग-अलग कुल रख सकता हूं जो किसी भी समय रिकॉर्ड जोड़ा जाता है, हटा दिया जाता है, या फ़ील्ड 2 संपादित किया जाता है। यह अनावश्यक है, लेकिन जब मैं कुल जानना चाहता हूं तो सुपर फास्ट। और मैं हमेशा SUM() कर सकता हूं अगर मैं अपने अलग गणना वाले कुल लेखापरीक्षा करना चाहता हूं।

0

हम्म ... बस अपनी पोस्ट को दो मिनट के लिए देख रहे हैं, इसलिए मेरा जवाब सही नहीं हो सकता है ... लेकिन क्या आपने एक इंडेक्स टेबल पेश करने का विचार किया है जो अन्य संस्थाओं से जुड़ा हुआ है?

CREATE TABLE `references` 
    `text` VARC>HAR(...) NOT NULL, 
    `name` VARCHAR(255) NOT NULL, 
    `reference_type` WHATEVER, // enum or what suits your needs 
    `reference_id` INTEGER NOT NULL 
); 

की तरह तो बस इस तालिका क्वेरी:

SELECT COUNT(*) FROM references WHERE sometext LIKE ...; 

हालांकि 'sometext%' के साथ मामलों को संभालने के लिए है चाहेंगे ...

इसके अलावा, गैलरी की संख्या वास्तव में महत्वपूर्ण है, या आपकी क्वेरी सिर्फ यह जांचने के लिए है कि कोई भी मौजूद है या नहीं?