2012-04-14 20 views
5

मेरे पास एक ही आदेश के बारे में जानकारी एकत्र करने के लिए यह प्रश्न है और यह काफी जटिल हो गया है।MySQL क्या इनरजॉइन की कोई सीमा है?

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

साथ ही, क्या INNER JOIN के बाद WHERE खंड होना वैध है?

आपकी सलाह के लिए धन्यवाद।

# Order: Get Order 

function getOrder($order_id) { 
    $sql = "SELECT (order.id, order.created, o_status.status, 
        /* payment info */ 
        order.total, p_status.status, 
        /* ordered by */ 
        cust_title.title, cust.forename, cust.surname, 
        customer.phone, customer.email, 
        cust.door_name, cust.street1, 
        cust.street2, cust.town, 
        cust.city, cust.postcode, 
        /* deliver to */ 
        recip_title.title, recipient.forename, recipient.surname, 
        recipient.door_name, recipient.street1, 
        recipient.street2, recipient.town, 
        recipient.city, recipient.postcode, 
        /* deliver info */ 
         shipping.name, order.memo, 
        /* meta data */ 
        order.last_update) 
       FROM tbl_order AS order 

     INNER JOIN tbl_order_st AS o_status 
       ON order.order_status_id = o_status.id 

     INNER JOIN tbl_payment_st AS p_status 
       ON order.payment_status_id = p_status.id 

     INNER JOIN (SELECT (cust_title.title, cust.forename, cust.surname, 
          customer.phone, customer.email, 
     /* ordered by */ cust.door_name, cust.street1, 
          cust.street2, cust.town, 
          cust.city, cust.postcode) 
         FROM tbl_customer AS customer 
       INNER JOIN tbl_contact AS cust 
          ON customer.contact_id = cust.id 
       INNER JOIN tbl_contact_title AS cust_title 
         ON cust.contact_title_id = cust_title.id 
        WHERE order.customer_id = customer.id) 
       ON order.customer_id = customer.id 

     INNER JOIN (SELECT (recip_title.title, recipient.forename, recipient.surname, 
     /* deliver to */ recipient.door_name, recipient.street1, 
          recipient.street2, recipient.town, 
          recipient.city, recipient.postcode) 
         FROM tbl_contact AS recipient 
       INNER JOIN tbl_contact_title AS recip_title 
         ON recipient.contact_title_id = recip_title.id 
        WHERE order.contact_id = recipient.id) 
       ON order.contact_id = recipient.id 

     INNER JOIN tbl_shipping_opt AS shipping 
       ON order.shipping_option_id = shipping.id 

      WHERE order.id = '?';"; 
    dbQuery($sql, array((int)$order_id)); 
    $rows = dbRowsAffected(); 
    if ($rows == 1) 
     return dbFetchAll(); 
    else 
     return null; 
} 

के बाद से किसी को इस प्रश्न के लिए स्कीमा का अनुरोध किया, यहाँ यह है:

# TBL_CONTACT_TITLE 

DROP TABLE IF EXISTS tbl_contact_title; 
CREATE TABLE tbl_contact_title(
    id INT NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY(id), 
    title CHAR(3) 
) ENGINE = InnoDB; 
INSERT INTO tbl_contact_title 
    (title) 
VALUES ('MR'), 
    ('MRS'), 
    ('MS'); 


# TBL_CONTACT 

DROP TABLE IF EXISTS tbl_contact; 
CREATE TABLE tbl_contact(
    id INT NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY(id), 
    contact_title_id INT, 
    FOREIGN KEY(contact_title_id) REFERENCES tbl_contact_title(id) ON DELETE SET NULL, 
    forename VARCHAR(50), 
    surname VARCHAR(50), 
    door_name VARCHAR(25), 
    street1 VARCHAR(40), 
    street2 VARCHAR(40), 
    town VARCHAR(40), 
    city VARCHAR(40), 
    postcode VARCHAR(10), 
    currency_id INT, 
    FOREIGN KEY(currency_id) REFERENCES tbl_currency(id) ON DELETE SET NULL 
) ENGINE = InnoDB; 

# TBL_CUSTOMER 

DROP TABLE IF EXISTS tbl_customer; 
CREATE TABLE tbl_customer(
    id INT NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY(id), 
    contact_id INT, 
    FOREIGN KEY(contact_id) REFERENCES tbl_contact(id) ON DELETE SET NULL, 
    birthday DATE, 
    is_male TINYINT, 
    phone VARCHAR(20), 
    email VARCHAR(50) NOT NULL 
) ENGINE = InnoDB, AUTO_INCREMENT = 1000; 

# TBL_ORDER_ST 

DROP TABLE IF EXISTS tbl_order_st; 
CREATE TABLE tbl_order_st(
    id INT NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY(id), 
    status VARCHAR(25) 
) ENGINE = InnoDB; 
INSERT INTO tbl_order_st 
    (status) 
VALUES 
    ('NEW'), 
    ('PROCESSING'), 
    ('SHIPPED'), 
    ('COMPLETED'), 
    ('CANCELLED'); 


# TBL_SHIPPING_OPT 

DROP TABLE IF EXISTS tbl_shipping_opt; 
CREATE TABLE tbl_shipping_opt(
    id INT NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY(id), 
    name VARCHAR(50), 
    description VARCHAR(255), 
    cost DECIMAL(6,3) 
) ENGINE = InnoDB; 
INSERT INTO tbl_shipping_opt 
    (name, description, cost) 
VALUES 
    ('UK Premier', 'U.K. Mainland upto 30KG, Next Working Day', 8.00), 
    ('Europe Standard', 'Most European Destinations* upto 30KG, 2 to 5 Working Days *please check before purchase', 15.00); 


# TBL_PAYMENT_ST 

DROP TABLE IF EXISTS tbl_payment_st; 
CREATE TABLE tbl_payment_st(
    id INT NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY(id), 
    status VARCHAR(25) 
) ENGINE = InnoDB; 
INSERT INTO tbl_payment_st 
    (status) 
VALUES 
    ('UNPAID'), 
    ('PAID'); 


# TBL_ORDER 

DROP TABLE IF EXISTS tbl_order; 
CREATE TABLE tbl_order(
    id INT NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY(id), 
    customer_id INT, 
     FOREIGN KEY(customer_id) REFERENCES tbl_customer(id) ON DELETE SET NULL, 
    contact_id INT, 
    FOREIGN KEY(contact_id) REFERENCES tbl_contact(id) ON DELETE SET NULL, 
    created DATETIME, 
    last_update TIMESTAMP, 
    memo VARCHAR(255), 
    order_status_id INT, 
    FOREIGN KEY(order_status_id) REFERENCES tbl_order_st(id), 
    shipping_option_id INT, 
    FOREIGN KEY(shipping_option_id) REFERENCES tbl_shipping_opt(id), 
    coupon_id INT, 
    FOREIGN KEY(coupon_id) REFERENCES tbl_coupon(id) ON DELETE SET NULL, 
    total DECIMAL(9,3), 
    payment_status_id INT, 
    FOREIGN KEY(payment_status_id) REFERENCES tbl_payment_st(id) 
) ENGINE = InnoDB, AUTO_INCREMENT = 1000; 
+2

इसे अधिकतम तक दबाएं। जब तक आपको कोई वाक्यविन्यास त्रुटियां या "बहुत अधिक शामिल" जैसी कोई चीज़ नहीं मिलती, तब तक आगे बढ़ें। – hakre

+0

@ हकर धन्यवाद ... मैं इसे तब लेता हूं, क्वेरी का आकार कोई फर्क नहीं पड़ता। – Ozzy

उत्तर

3

आपके पास MySQL के लिए जॉइन की सीमा के पास कहीं भी नहीं है। आपकी जॉइन की संख्या खराब नहीं है। हालांकि, एक व्युत्पन्न तालिका (आपकी आंतरिक सबक्वायरी) में शामिल होने पर आप प्रदर्शन के मुद्दों का कारण बन सकते हैं, क्योंकि व्युत्पन्न तालिकाओं में इंडेक्स नहीं होते हैं। इंडेक्स के बिना व्युत्पन्न तालिका में शामिल होना धीमा हो सकता है।

आपको शामिल होने के लिए इंडेक्स के साथ एक वास्तविक अस्थायी तालिका बनाने पर विचार करना चाहिए, या सबक्वायरी से बचने के लिए एक तरीका पता लगाना चाहिए।

MySQL में जॉइन मूल रूप से प्रत्येक शामिल पंक्ति के लिए एक लुकअप (तलाश) करना पसंद है। इसलिए, यदि आप कई रिकॉर्ड में शामिल हो रहे हैं तो MySQL को कई लुकअप करना होगा। यह आपके बारे में कम है कि आप पंक्तियों की संख्या से कितनी तालिकाओं में शामिल होते हैं जो एक समस्या हो सकती है।

वैसे भी, MySQL केवल छोड़ने से पहले इतने सारे प्रयास करेगा और केवल पूरी तालिका को पढ़ेगा। यह निर्णय लेने में एक बहुत अच्छा काम करता है जो कम महंगा होगा।

शायद सबसे अच्छी बात यह है कि आप एनालिज टेबल के साथ इंडेक्स आंकड़ों को अपडेट करके अनुमान लगा सकते हैं।

आपके पास प्रति चयन एक कहां है। तो आपके भीतर की सबक्वायरी में एक WHERE क्लॉज होगा और आपकी बाहरी क्वेरी में WHERE क्लॉज होगा, और इन्हें जॉइन के बाद लागू किया जाएगा (कम से कम तार्किक रूप से, हालांकि MySQL आम तौर पर उन्हें प्रदर्शन के लिए पहले लागू करेगा)।

इसके अलावा, यह सब आपको लगता है कि आप इंडेक्स का सही तरीके से उपयोग कैसे करें।

+0

मुझे यह जवाब स्वीकार करने में खुशी है। यदि मेरे पास प्रदर्शन समस्याएं हैं, तो मैं सिर्फ एक और तालिका बना सकता हूं (जैसा कि आपने सुझाव दिया है) लेकिन मैं इसे छोड़ दूंगा क्योंकि यह अभी के लिए है। मुझे अभी तक अनुक्रमण का कोई ज्ञान नहीं है ... मुझे कुछ टट्स पढ़ना होगा। धन्यवाद @ मार्कस-एडम्स – Ozzy

1

मैं किसी भी सामान्य सलाह, बस अपने ही expirience की जरूरत नहीं है

क्वेरी है।

मुझे एक बार बहुत खराब प्रदर्शन के साथ समस्या थी जहां मैंने जॉइन का उपयोग करके टेबल का टन जोड़ा। लगभग 20 जॉइन मैंने किया था। जब मैंने परीक्षण में कुछ जॉइन हटा दिए तो गति फिर से बढ़ी। इस तथ्य के कारण मुझे केवल एक ही जानकारी की आवश्यकता थी, मैं उप-चयनों के साथ अधिकांश जॉइन को प्रतिस्थापित करने में सक्षम था। इसने मेरी क्वेरी के लिए 25 सेकंड से मेरी समस्या को कम करने के बाद 1 सेकंड तक हल किया।

यह शायद आपके टेबल डिज़ाइन, जुड़ी हुई तालिकाओं की कॉलम की मात्रा और आपके इंडेक्स में शामिल होने पर एक सूचकांक है।

+0

तो आप कह रहे हैं कि मेरे पास बड़ी पूछताछ हो सकती है लेकिन उप-चयन जॉइन सिंटैक्स से तेज़ तरीका है? – Ozzy

+1

मुझे लगता है कि यह क्वेरी पर ही निर्भर करता है। मेरे मामले में सब सही इंडेक्स सेटअप के साथ तेजी से कहां से चुनता है। – YvesR

+0

मुझे लगता है कि आपको अपनी सभी जरूरतों में शामिल होना चाहिए और फिर इसे सरल बनाना शुरू करें (केवल कॉलम 1 डेटा के लिए उप चयन और उसी डेटा के विलय) – YvesR

2

अच्छी तरह से मैंने एक बार स्वयं जुड़ने की संख्या के लिए सीमा देखने के लिए कोशिश की और मैंने इसे सही ढंग से याद करते हुए mysql 5.0.4 पर 100 तालिकाओं के साथ जुड़ने का परीक्षण किया।

Too many tables. MySQL can only use 61 tables in a join.

मुझे लगता है कि MySql 4 के लिए सीमा 31 टेबल था:

मैं निम्न त्रुटि दिया गया था।

यदि आप किसी क्वेरी में कई तालिकाओं का उपयोग करने की योजना बना रहे हैं तो सलाह का एक शब्द तो आपके प्रश्न डिजाइन को सरल बनाने के बारे में सोचने का समय है।

+0

+1 (धन्यवाद)। मुझे लगता है कि जानकारी इसे मेरे लिए परिप्रेक्ष्य में रखती है, मेरी 8 संभावित 61 में से जुड़ती है, बुरा नहीं हो सकता है। – Ozzy

2

मैं इसके लिए भी खोज कर रहा था, और फिर मुझे यह अन्य समाधान मिला, "जॉइन" के हिस्से के रूप में "और" जोड़ना।

INNER JOIN kopplaMedlemIntresse 
ON intressen.id = kopplaMedlemIntresse.intresse_id AND kopplaMedlemIntresse.medlem_id = 3 
संबंधित मुद्दे