अधिक प्रदर्शन करने वाले, CTE या अस्थायी टेबल कौन से हैं?


136

कौन से कलाकार अधिक हैं, CTEया Temporary Tables?


3
संबंधित प्रश्न: dba.stackexchange.com/q/13112
राहेल

उपयोगकर्ता Technet.microsoft.com पर कॉमन टेबल एक्सप्रेशंस पृष्ठ का उपयोग करके पृष्ठभूमि की जानकारी (प्रदर्शन से संबंधित नहीं) पा सकते हैं ।
शेरिडन

जवाबों:


62

मैं कहता हूं कि वे अलग अवधारणाएं हैं, लेकिन "चॉक और पनीर" कहने के लिए बहुत अलग नहीं हैं।

  • डेटा के एक सेट पर पुन: उपयोग करने या कई प्रसंस्करण पास करने के लिए एक अस्थायी तालिका अच्छी है।

  • एक सीटीई का उपयोग या तो पुनरावृत्ति के लिए या केवल पठनीयता में सुधार के लिए किया जा सकता है।
    और, एक दृश्य या इनलाइन तालिका मूल्यवान फ़ंक्शन की तरह भी मुख्य क्वेरी में विस्तारित होने के लिए मैक्रो की तरह व्यवहार किया जा सकता है

  • एक अस्थायी तालिका एक और तालिका है जिसमें कुछ नियम हैं

मैंने जहाँ मैं (और तालिका चर दोनों) का उपयोग करता है, वहां प्रोक्स संग्रहीत किए हैं


12
अस्थायी तालिकाएँ अनुक्रमित और यहां तक ​​कि सांख्यिकी के लिए भी अनुमति देती हैं जो कभी-कभी आवश्यक होती हैं, जबकि सीटीई नहीं करता है।
कोडकॉवॉयऑर्ग 15

9
मुझे लगता है कि यह उत्तर इस तथ्य को उजागर नहीं करता है कि सीटीई के कारण भयानक प्रदर्शन हो सकता है। मैं आमतौर पर dba.stackexchange पर इस उत्तर को संदर्भित करता हूं। आपका प्रश्न मेरे खोज इंजन में दूसरे स्थान पर आता है अगर मैं देख रहा हूँ cte vs temporary tablesतो IMHO इस उत्तर को CTE के बेहतर कमियों को उजागर करने की आवश्यकता है। लिंक किए गए उत्तर के टीएल; डीआर: एक सीटीई का उपयोग प्रदर्शन के लिए कभी नहीं किया जाना चाहिए। । मैं उस उद्धरण से सहमत हूं क्योंकि मैंने सीटीई के डाउनसाइड्स का अनुभव किया है।
टीटी।

2
@TT। दिलचस्प। मुझे लगता है कि सीटीई बहुत बेहतर प्रदर्शन करते हैं
स्क्वेअर 3lz

198

निर्भर करता है।

सबसे पहले

कॉमन टेबल एक्सप्रेशन क्या है?

A (गैर पुनरावर्ती) CTE को अन्य निर्माणों के समान माना जाता है जिनका उपयोग SQL सर्वर में इनलाइन टेबल एक्सप्रेशन के रूप में भी किया जा सकता है। व्युत्पन्न टेबल, दृश्य और इनलाइन तालिका मूल्यवान कार्य। ध्यान दें कि बीओएल का कहना है कि एक सीटीई "को अस्थायी परिणाम सेट के रूप में माना जा सकता है" यह एक विशुद्ध रूप से तार्किक विवरण है। अधिक बार नहीं यह अपने आप में मातृसत्तात्मक नहीं है।

अस्थायी तालिका क्या है?

यह tempdb में डेटा पृष्ठों पर संग्रहीत पंक्तियों का एक संग्रह है। डेटा पेज आंशिक रूप से या पूरी तरह से मेमोरी में रह सकते हैं। इसके अतिरिक्त अस्थायी तालिका को अनुक्रमित किया जा सकता है और कॉलम आँकड़े हो सकते हैं।

परीक्षण डेटा

CREATE TABLE T(A INT IDENTITY PRIMARY KEY, B INT , F CHAR(8000) NULL);

INSERT INTO T(B)
SELECT TOP (1000000)  0 + CAST(NEWID() AS BINARY(4))
FROM master..spt_values v1,
     master..spt_values v2;

उदाहरण 1

WITH CTE1 AS
(
SELECT A,
       ABS(B) AS Abs_B,
       F
FROM T
)
SELECT *
FROM CTE1
WHERE A = 780

योजना 1

ऊपर की योजना में सूचना CTE1 का कोई उल्लेख नहीं है। यह बस बेस टेबल को सीधे एक्सेस करता है और इसे उसी तरह माना जाता है

SELECT A,
       ABS(B) AS Abs_B,
       F
FROM   T
WHERE  A = 780 

CTE को इंटरमीडिएट अस्थायी तालिका में शामिल करके फिर से तैयार करना बड़े पैमाने पर उत्पादक होगा।

की सीटीई परिभाषा को भौतिक बनाना

SELECT A,
       ABS(B) AS Abs_B,
       F
FROM T

एक अस्थायी तालिका में लगभग 8GB डेटा की नकल करना शामिल होगा, फिर भी उसमें से चयन करने का ओवरहेड अभी भी है।

उदाहरण 2

WITH CTE2
     AS (SELECT *,
                ROW_NUMBER() OVER (ORDER BY A) AS RN
         FROM   T
         WHERE  B % 100000 = 0)
SELECT *
FROM   CTE2 T1
       CROSS APPLY (SELECT TOP (1) *
                    FROM   CTE2 T2
                    WHERE  T2.A > T1.A
                    ORDER  BY T2.A) CA 

उपरोक्त उदाहरण मेरी मशीन पर लगभग 4 मिनट लगते हैं।

1,000,000 यादृच्छिक रूप से उत्पन्न मानों की केवल 15 पंक्तियाँ विधेय से मेल खाती हैं लेकिन इनको खोजने के लिए महंगी तालिका स्कैन 16 बार होता है।

यहां छवि विवरण दर्ज करें

यह मध्यवर्ती परिणाम के लिए एक अच्छा उम्मीदवार होगा। समतुल्य अस्थायी तालिका पुनर्लेखन में 25 सेकंड लगे।

INSERT INTO #T
SELECT *,
       ROW_NUMBER() OVER (ORDER BY A) AS RN
FROM   T
WHERE  B % 100000 = 0

SELECT *
FROM   #T T1
       CROSS APPLY (SELECT TOP (1) *
                    FROM   #T T2
                    WHERE  T2.A > T1.A
                    ORDER  BY T2.A) CA 

प्लान के साथ

एक अस्थायी तालिका में एक क्वेरी के हिस्से का मध्यवर्ती भौतिककरण कभी-कभी उपयोगी हो सकता है, भले ही इसका मूल्यांकन केवल एक बार किया जाए - जब यह क्वेरी के बाकी हिस्सों को भौतिक परिणाम पर आँकड़ों का लाभ लेने की अनुमति देता है। इस दृष्टिकोण का एक उदाहरण SQL कैट के लेख में है जब कॉम्प्लेक्स क्वेरीज़ को तोड़ना है

कुछ परिस्थितियों में SQL सर्वर एक स्पूल का उपयोग एक मध्यवर्ती परिणाम को कैश करने के लिए करेगा, उदाहरण के लिए एक सीटीई, और इस उप-वृक्ष का पुनर्मूल्यांकन करने से बचें। इसमें (माइग्रेट किए गए) कनेक्ट आइटम पर चर्चा की गई है जो सीटीई या व्युत्पन्न तालिकाओं के मध्यवर्ती भौतिककरण को मजबूर करने के लिए एक संकेत प्रदान करता है । हालाँकि, इस पर कोई आंकड़े नहीं बनाए गए हैं और भले ही स्पूल की गई पंक्तियों की संख्या अनुमानित रूप से भिन्न हो, प्रगति निष्पादन योजना के गतिशील रूप से प्रतिक्रिया में अनुकूल होने के लिए संभव नहीं है (कम से कम वर्तमान संस्करणों में। अनुकूली क्वेरी योजनाएँ संभव हो सकती हैं। भविष्य)।


33
यह एकमात्र ऐसा उत्तर है जो वास्तविक प्रश्न का उत्तर देता है (जो पूछ रहा है कि बेहतर प्रदर्शन क्या अंतर है या जो आपका पसंदीदा है), और यह उस प्रश्न का सही उत्तर देता है: "यह निर्भर करता है" सही उत्तर है। यह समझाने के लिए सहायक डेटा के साथ एकमात्र उत्तर भी है, कई अन्य (वोटों की उच्च संख्या के साथ) निश्चित दावे करते हैं कि कोई भी संदर्भ या प्रमाण के साथ दूसरे की तुलना में बेहतर है ... स्पष्ट होने के लिए, उन सभी उत्तर भी गलत हैं । क्योंकि "यह निर्भर करता है"
Arkaine55

2
यह एक अच्छी तरह से लिखा, अच्छी तरह से संदर्भित उत्तर भी है। गंभीरता से शीर्ष पायदान।
डैन विलियम्स

50

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


9
मैंने इसे अपने अनुभव से देखा है। CTE का प्रदर्शन काफी धीमा है।
गोकू_डा_मास्टर

7
सीटीई भी धीमी गति से करते हैं क्योंकि परिणाम कैश नहीं होते हैं। तो हर बार जब आप सीटीई का उपयोग करते हैं तो यह क्वेरी, योजना और सभी को फिर से चलाता है।
गोकू_डा_मास्टर

1
और डीबी इंजन क्वेरी को न केवल हर संदर्भ में चलाने के लिए चुन सकता है, बल्कि उपभोक्ता क्वेरी की प्रत्येक पंक्ति के लिए, एक सहसंबद्ध उपश्रेणी के रूप में ... आपको हमेशा इसके लिए बाहर देखना होगा, यदि यह वांछित नहीं है।
माइक एम।

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

33

टेंप टेबल हमेशा डिस्क पर होती हैं - इसलिए जब तक आपकी सीटीई को मेमोरी में रखा जा सकता है, तब तक इसकी संभावना सबसे तेज होगी (जैसे टेबल वेरिएबल भी)।

लेकिन फिर, यदि आपके CTE (या अस्थायी तालिका चर) का डेटा लोड बहुत बड़ा हो जाता है, तो इसे डिस्क पर संग्रहीत किया जाएगा, इसलिए कोई बड़ा लाभ नहीं है।

सामान्य तौर पर, मैं एक अस्थायी तालिका के ऊपर एक सीटीई पसंद करता हूं क्योंकि इसका उपयोग करने के बाद यह चला गया है। मुझे इसे स्पष्ट रूप से या कुछ भी छोड़ने के बारे में सोचने की आवश्यकता नहीं है।

इसलिए, अंत में कोई स्पष्ट जवाब नहीं है, लेकिन व्यक्तिगत रूप से, मैं अस्थायी टेबल पर सीटीई पसंद करूंगा।


2
SQLite और PostgreSQL के मामले में, अस्थायी तालिकाओं को स्वचालित रूप से गिरा दिया जाता है (आमतौर पर एक सत्र के अंत में)। मैं हालांकि अन्य DBMS के बारे में नहीं जानता।
सेरानो

1
CTE एक टेम्प व्यू की तरह है। AFAIK डेटा को संग्रहीत नहीं किया जाता है इसलिए कुछ भी वैन मेमोरी में नहीं रखा जाता है या डिस्क पर संग्रहीत नहीं किया जाता है। महत्वपूर्ण नोट, हर बार जब आप सीटीई का उपयोग करते हैं तो क्वेरी फिर से चलती है।
रोब

1
व्यक्तिगत रूप से मैंने कभी भी CTE को गति के लिए टेंप टेबल से बेहतर काम करते नहीं देखा। और
टेम्पिंग

7

इसलिए जो क्वेरी मुझे ऑप्टिमाइज़ करने के लिए दी गई थी, वह SQL सर्वर में दो CTE के साथ लिखी गई थी। इसमें 28 सेकेंड का समय लग रहा था।

मैंने उन्हें टेम्‍प टेबल में बदलने में दो मिनट का समय लगाया और क्‍वेरी को 3 सेकंड का समय लगा

जिस फील्ड में यह शामिल हो रहा था, उस पर मैंने टेम्पर टेबल में एक इंडेक्स जोड़ा और इसे 2 सेकंड तक नीचे कर दिया

तीन मिनट का काम और अब CTE को हटाकर इसका रनिंग 12 गुना तेज हो गया है। मैं व्यक्तिगत रूप से सीटीई का उपयोग नहीं करूंगा, वे कभी-कभी डिबग करने के लिए कठिन हैं।

पागल बात यह है कि सीटीई दोनों केवल एक बार उपयोग किए गए थे और अभी भी उन पर एक इंडेक्स डालना 50% तेज साबित हुआ।


6

CTE कोई भौतिक स्थान नहीं लेगा। यह सिर्फ एक परिणाम है जो हम शामिल होने का उपयोग कर सकते हैं।

अस्थायी टेबल अस्थायी हैं। हम सभी तालिकाओं को परिभाषित करने के लिए सामान्य तालिकाओं की तरह अनुक्रमित, बाधाएं बना सकते हैं।

केवल सत्र के भीतर अस्थायी तालिका का दायरा। EX: दो SQL क्वेरी विंडो खोलें

create table #temp(empid int,empname varchar)
insert into #temp 
select 101,'xxx'

select * from #temp

इस क्वेरी को पहले विंडो में चलाएं फिर नीचे की क्वेरी को दूसरी विंडो में चलाएं आप अंतर पा सकते हैं।

select * from #temp

4
>> "यह सिर्फ एक परिणाम सेट है जिसका उपयोग हम जुड़ने के लिए कर सकते हैं।" -> यह सटीक नहीं है। CTE एक "परिणाम सेट" नहीं है, लेकिन इनलाइन कोड है। SQL सर्वर क्वेरी इंजन क्वेरी पाठ के भाग के रूप में सीटीई कोड को पार्स करता है और उसी के अनुसार एक निष्पादन योजना बनाता है। यह विचार है कि CTE इनलाइन है CTE का उपयोग करने का बड़ा फायदा, क्योंकि यह सर्वर को "कंबाइन निष्पादन योजना" बनाने की अनुमति देता है
Ronen Ariely

4

मैंने दोनों का उपयोग किया है, लेकिन बड़े जटिल प्रक्रियाओं में हमेशा अस्थायी तालिकाओं को बेहतर और अधिक व्यवस्थित रूप से काम करने के लिए मिला है। CTE के अपने उपयोग हैं लेकिन आम तौर पर छोटे डेटा के साथ।

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


3

पार्टी के लिए देर से, लेकिन ...

जिस वातावरण में मैं काम करता हूं वह अत्यधिक विवश है, कुछ विक्रेता उत्पादों का समर्थन करता है और रिपोर्टिंग जैसी "मूल्य वर्धित" सेवाएं प्रदान करता है। नीति और अनुबंध सीमाओं के कारण, मुझे आमतौर पर अलग-अलग टेबल / डेटा स्पेस की लक्जरी और / या स्थायी कोड बनाने की क्षमता की अनुमति नहीं दी जाती है [यह आवेदन के आधार पर थोड़ा बेहतर हो जाता है]।

IOW, मैं नहीं कर सकता आमतौर पर एक संग्रहीत कार्यविधि या UDFs या अस्थायी सारणी आदि विकसित । मुझे अपने एप्लीकेशन इंटरफेस (क्रिस्टल रिपोर्ट्स - ऐड / लिंक टेबल्स) के माध्यम से सब कुछ करना है, जहाँ से CR में w / से क्लॉस आते हैं, आदि। )। एक लघु बचत अनुग्रह यह है कि क्रिस्टल मुझे COMMANDS (साथ ही SQL एक्सप्रेशंस) का उपयोग करने की अनुमति देता है। कुछ चीजें जो नियमित ऐड / लिंक टेबल क्षमता के माध्यम से कुशल नहीं हैं, उन्हें SQL कमांड को परिभाषित करके किया जा सकता है। मैं उस के माध्यम से सीटीई का उपयोग करता हूं और "दूरस्थ रूप से" बहुत अच्छे परिणाम प्राप्त करता हूं। CTEs w / रिपोर्ट रखरखाव में मदद करते हैं, उस कोड को विकसित करने की आवश्यकता नहीं है, संकलन, एन्क्रिप्ट, स्थानांतरण, इंस्टॉल करने के लिए DBA को सौंप दिया जाता है, और फिर कई-स्तरीय परीक्षण की आवश्यकता होती है। मैं स्थानीय इंटरफ़ेस के माध्यम से सीटीई कर सकता हूं।

CTEs w / CR का उपयोग करने का डाउन साइड है, प्रत्येक रिपोर्ट अलग है। प्रत्येक रिपोर्ट के लिए प्रत्येक सीटीई को बनाए रखा जाना चाहिए। जहां मैं एसपी और यूडीएफ कर सकता हूं, मैं एक ऐसी चीज विकसित कर सकता हूं जिसका उपयोग कई रिपोर्टों द्वारा किया जा सकता है, केवल एसपी से लिंक करने और मापदंडों को पारित करने की आवश्यकता होती है जैसे कि आप एक नियमित टेबल पर काम कर रहे थे। सीआर वास्तव में एसक्यूएल कमांड में मापदंडों को संभालने के लिए अच्छा नहीं है, ताकि सीआर / सीटीई पहलू के पहलू की कमी हो सकती है। उन मामलों में, मैं आमतौर पर पर्याप्त डेटा (लेकिन सभी डेटा नहीं) वापस करने के लिए सीटीई को परिभाषित करने की कोशिश करता हूं, और फिर सीआर में रिकॉर्ड चयन क्षमताओं का उपयोग स्लाइस और पासा करने के लिए करता हूं।

इसलिए ... मेरा वोट सीटीई के लिए है (जब तक मुझे अपना डेटा स्पेस नहीं मिल जाता)।


3

एक उपयोग जहां मुझे CTE का उत्कृष्ट प्रदर्शन बुद्धिमान मिला, वह यह था कि मुझे कुछ तालिकाओं पर अपेक्षाकृत जटिल क्वेरी में शामिल होने की आवश्यकता थी, जिसमें कुछ मिलियन पंक्तियाँ थीं।

मैंने सबसे पहले CTE का उपयोग अनुक्रमित स्तंभों के आधार पर सबसे पहले इन तालिकाओं को काटकर कुछ हज़ार प्रासंगिक पंक्तियों में करने के लिए किया और फिर CTE को मेरी मुख्य क्वेरी में शामिल किया। इसने तेजी से मेरी क्वेरी के रनटाइम को कम कर दिया।

सीटीई के लिए जब भी नतीजे कैश नहीं होते हैं और टेबल वेरिएबल एक बेहतर विकल्प हो सकता है, तो मैं वास्तव में बस उन्हें आज़माना चाहता था और फिट होना चाहिए।


इसके अलावा, मुझे लगता है कि जब से मैं केवल CTE में शामिल होने में मैं केवल वास्तव में CTE पर अमल का उपयोग अपनी क्वेरी में एक बार तो परिणाम कैशिंग इस संबंध में इतनी बड़ी मुद्दा नहीं था
purchas

1

यह वास्तव में खुला हुआ प्रश्न है, और यह सब इस बात पर निर्भर करता है कि इसका उपयोग कैसे किया जा रहा है और टेम्‍प टेबल का प्रकार (टेबल चर या पारंपरिक तालिका)।

एक पारंपरिक अस्थायी तालिका डेटा को अस्थायी DB में संग्रहीत करती है, जो अस्थायी तालिकाओं को धीमा कर देती है; हालांकि टेबल चर नहीं है।


1

मैंने अभी इसका परीक्षण किया- सीटीई और गैर-सीटीई (जहां हर यूनियन उदाहरण के लिए क्वेरी टाइप की गई थी) दोनों ने ~ 31 सेकंड का समय लिया। CTE ने कोड को अधिक पठनीय बना दिया, हालांकि इसे 241 से 130 लाइनों तक काट दिया जो बहुत अच्छा है। दूसरी ओर अस्थायी तालिका ने इसे 132 रेखाओं तक काट दिया, और चलाने के लिए FIVE SECONDS लिया। कोई मजाक नहीं। इस परीक्षण के सभी को कैश किया गया था - प्रश्न पहले सभी कई बार चलाए गए थे।


1

SQL सर्वर में अपने अनुभव से, मुझे एक परिदृश्य मिला जहां CTE ने टेम्पर टेबल को बेहतर बनाया

मुझे एक जटिल क्वेरी से डेटासेट (~ 100000) का उपयोग करने की आवश्यकता थी बस मेरे संग्रहीत कार्यविधि में ONCE।

  • टेंप टेबल एसक्यूएल पर एक ओवरहेड का कारण बन रही थी जहां मेरी प्रक्रिया धीरे-धीरे प्रदर्शन कर रही थी (जैसे कि टेंप टेबल्स वास्तविक भौतिक तालिकाओं हैं जो टेम्पर्डब में मौजूद हैं और मेरी वर्तमान प्रक्रिया के जीवन के लिए जारी रहती हैं)

  • दूसरी ओर, सीटीई के साथ, सीटीई पर्सिस्ट केवल तभी तक चलता है जब तक कि निम्नलिखित क्वेरी नहीं चलती। तो, CTE सीमित स्कोप के साथ एक आसान स्मृति संरचना है। CTE डिफ़ॉल्ट रूप से tempdb का उपयोग नहीं करते हैं।

यह एक ऐसा परिदृश्य है जहां सीटीई वास्तव में आपके कोड और आउटपरफॉर्म टेम्प टेबल को सरल बनाने में मदद कर सकता है। मैंने 2 सीटीई का उपयोग किया था, कुछ ऐसा

WITH CTE1(ID, Name, Display) 
AS (SELECT ID,Name,Display from Table1 where <Some Condition>),
CTE2(ID,Name,<col3>) AS (SELECT ID, Name,<> FROM CTE1 INNER JOIN Table2 <Some Condition>)
SELECT CTE2.ID,CTE2.<col3>
FROM CTE2
GO

1
आपका उत्तर बहुत सामान्य लगता है ... आप कैसे मापते हैं कि "सीटीई आउटपरफॉर्म टेंप टेबल"? क्या आपको कुछ समय माप मिला है? मेरी राय में आपको अपना उत्तर संपादित करना चाहिए और अधिक विवरण जोड़ना चाहिए।
इल विक

हाँ, मेरे बयान का समर्थन करने के लिए समय मापन और निष्पादन योजना है।
अमरदीप कोहली

सीमित विशेषाधिकारों के कारण निष्पादन योजना के लिए img नहीं जोड़ा जा सकता है। इसे हल करने के बाद अपडेट विवरण दें
अमरदीप कोहली
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.