मैं बिल कार्विन के उत्कृष्ट उत्तर के सभी बिंदुओं से सहमत हूं।
प्रश्न: क्या चर्चा की गई यूनियन क्वेरी के लिए एक दृश्य बनाना और मेरे जॉइन, सबसेलेक्ट आदि में इसका उपयोग करना सामान्य बात है?
ए: MySQL के साथ "क्रिएट व्यू" स्टेटमेंट का उपयोग करने से बचना अधिक सामान्य अभ्यास है।
प्रश्न: प्रदर्शन के संदर्भ में - क्या यह सिर्फ जुड़ने, उप-चयन आदि में डालने की तुलना में बदतर, बराबर या बेहतर होगा?
ए: किसी दृश्य वस्तु को संदर्भित करने का प्रदर्शन समान इनलाइन दृश्य के समान होगा।
(दृश्य वस्तु को देखने, विशेषाधिकारों की जांच करने, और फिर संग्रहीत एसक्यूएल के साथ दृश्य संदर्भ को प्रतिस्थापित करने के लिए एक किशोर-छोटा थोड़ा और काम हो सकता है, बनाम एक बयान भेजना जो केवल एक छोटा-छोटा सा लंबा है। लेकिन उनमें से कोई भी मतभेद महत्वहीन हैं।)
प्रश्न: क्या इस मामले में दृष्टिकोण रखने में कोई कमियां हैं?
ए: सबसे बड़ी कमी यह है कि MySQL किसी दृश्य को कैसे संसाधित करता है, चाहे वह संग्रहीत हो या इनलाइन। MySQL हमेशा दृश्य क्वेरी चलाएगा और उस क्वेरी के परिणामों को अस्थायी MyISAM तालिका के रूप में अमल में लाएगा। लेकिन इसमें कोई अंतर नहीं है कि क्या दृश्य परिभाषा संग्रहीत है, या क्या यह इनलाइन शामिल है। (अन्य RDBMS, MySQL की तुलना में बहुत अलग तरीके से विचारों की प्रक्रिया करते हैं)।
एक दृश्य की एक बड़ी कमी यह है कि बाहरी क्वेरी से विधेय कभी भी दृश्य क्वेरी में नीचे धकेला नहीं जाता है। हर बार जब आप उस दृश्य को संदर्भित करते हैं, यहां तक कि एक आईडी मान के लिए एक क्वेरी के साथ, MySQL दृश्य क्वेरी को चलाने और एक अस्थायी MyISAM तालिका (इस पर कोई अनुक्रमणिका के साथ) बनाने के लिए जा रहा है, और तब MySQL उस अस्थायी के खिलाफ बाहरी क्वेरी चलाएगा माईसाम टेबल।
इसलिए, प्रदर्शन के संदर्भ में, "CREATE TEMPORARY TABLE t (cols) ENGINE=MyISAM
के समान दृश्य के संदर्भ के बारे में सोचें। " और "INSERT INTO t (cols) SELECT ...
".
MySQL वास्तव में एक इनलाइन दृश्य को "व्युत्पन्न तालिका" के रूप में संदर्भित करता है, और यह नाम बहुत मायने रखता है, जब हम समझते हैं कि MySQL इसके साथ क्या कर रहा है।
मेरी व्यक्तिगत प्राथमिकता "क्रिएट व्यू" स्टेटमेंट का उपयोग नहीं करना है। सबसे बड़ी कमी (जैसा कि मैं इसे देखता हूं) यह है कि यह SQL को "छुपा" देता है जिसे निष्पादित किया जा रहा है। भविष्य के पाठक के लिए, दृश्य का संदर्भ एक तालिका जैसा दिखता है। और फिर, जब वह एक एसक्यूएल स्टेटमेंट लिखने जाता है, तो वह उस दृश्य को संदर्भित करने जा रहा है जैसे कि यह एक टेबल था, बहुत सुविधाजनक। फिर वह तय करता है कि वह उस तालिका में खुद से जुड़ने जा रहा है, इसके एक अन्य संदर्भ के साथ। (दूसरे संदर्भ के लिए, MySQL भी उस क्वेरी को फिर से चलाता है, और एक और अस्थायी (और unindexed) MyISAM तालिका बनाता है। और अब उस पर एक जॉइन ऑपरेशन है। और फिर एक विधेय "WHERE view.column ='foo'" जुड़ जाता है बाहरी क्वेरी पर।
यह सबसे स्पष्ट प्रदर्शन सुधार को "छिपाने" को समाप्त करता है, जो कि दृश्य क्वेरी में विधेय को स्लाइड करता है।
और फिर, कोई साथ आता है और निर्णय लेता है कि वे एक नया दृश्य बनाने जा रहे हैं, जो पुराने दृष्टिकोण का संदर्भ देता है। उसे केवल पंक्तियों के एक उपसमुच्चय की आवश्यकता है, और वह मौजूदा दृश्य को संशोधित नहीं कर सकता क्योंकि वह कुछ तोड़ सकता है, इसलिए वह एक नया दृश्य बनाता है... सार्वजनिक दृश्य से मेरा दृश्य देखें p जहां p.col ='foo'।
और, अब, myview का एक संदर्भ पहले पब्लिकव्यू क्वेरी को चलाने वाला है, एक अस्थायी MyISAM तालिका बनाने जा रहा है, फिर उसके विरुद्ध myview क्वेरी चलाई जाती है, जिससे एक और अस्थायी MyISAM तालिका बनती है, जिसके विरुद्ध बाहरी क्वेरी चलने वाली है।
मूल रूप से, दृश्य की सुविधा में अनजाने में प्रदर्शन समस्याओं की संभावना है। किसी के भी उपयोग के लिए डेटाबेस पर उपलब्ध दृश्य परिभाषा के साथ, कोई इसका उपयोग करने जा रहा है, यहां तक कि जहां यह सबसे उपयुक्त समाधान नहीं है।
कम से कम एक इनलाइन दृश्य के साथ, SQL कथन लिखने वाला व्यक्ति वास्तविक SQL निष्पादित होने के बारे में अधिक जागरूक होता है, और जो कुछ SQL निर्धारित किया जाता है उसे प्रदर्शन के लिए इसे ट्विक करने का अवसर मिलता है।
मेरे दो सेंट।
सर्वश्रेष्ठ एसक्यूएल को वश में करना
मुझे लगता है कि नियमित स्वरूपण नियम लागू करना (जो मेरे उपकरण स्वचालित रूप से करते हैं) राक्षसी एसक्यूएल को उस चीज़ में मोड़ सकते हैं जिसे मैं पढ़ सकता हूं और साथ काम कर सकता हूं।
SELECT row.col1
, row.col2
, person.*
FROM some_table row
LEFT
JOIN ( SELECT 'person' AS `person_type`
, p.id AS `id`
, CONCAT(p.first_name,' ',p.surname) AS `name`
FROM person p
UNION ALL
SELECT 'company' AS `person_type`
, c.id AS `id`
, c.name AS `name`
FROM company c
) person
ON person.id = row.person_id
AND person.person_type = row.person_type
मैं समान रूप से इनलाइन दृश्य से बचने की संभावना रखता हूं, और चयन सूची में सशर्त अभिव्यक्तियों का उपयोग करता हूं, हालांकि यह बहुत सारे कॉलम के लिए अधिक बोझिल हो जाता है।
SELECT row.col1
, row.col2
, row.person_type AS ref_person_type
, row.person_id AS ref_person_id
, CASE
WHEN row.person_type = 'person' THEN p.id
WHEN row.person_type = 'company' THEN c.id
END AS `person_id`
, CASE
WHEN row.person_type = 'person' THEN CONCAT(p.first_name,' ',p.surname)
WHEN row.person_type = 'company' THEN c.name
END AS `name`
FROM some_table row
LEFT
JOIN person p
ON row.person_type = 'person'
AND p.id = row.person_id
LEFT
JOIN company c
ON row.person_type = 'company'
AND c.id = row.person_id