เบื้องหลังฉากของไฟร์วอลล์ความเป็นส่วนตัวของข้อมูล
หมายเหตุ
ขณะนี้ระดับความเป็นส่วนตัวไม่พร้อมใช้งานในกระแสข้อมูล Power Platform แต่ทีมผลิตภัณฑ์กําลังทํางานเพื่อเปิดใช้งานฟังก์ชันนี้
หากคุณใช้ Power Query เป็นระยะเวลานานแล้ว คุณอาจเคยประสบ คุณมีการคิวรี่ออกไปเมื่อคุณได้รับข้อผิดพลาดทันทีที่ไม่มีจํานวนการค้นหาออนไลน์การปรับแต่งคิวรี่หรือการตีด้วยแป้นพิมพ์สามารถแก้ไขได้ ข้อผิดพลาดเช่น:
Formula.Firewall: Query 'Query1' (step 'Source') references other queries or steps, so it may not directly access a data source. Please rebuild this data combination.
หรืออาจจะ:
Formula.Firewall: Query 'Query1' (step 'Source') is accessing data sources that have privacy levels which cannot be used together. Please rebuild this data combination.
ข้อผิดพลาดเหล่านี้ Formula.Firewall
เป็นผลลัพธ์ของไฟร์วอลล์ความเป็นส่วนตัวของข้อมูลของ Power Query (หรือที่เรียกว่าไฟร์วอลล์) ซึ่งในบางครั้งอาจดูเหมือนว่ามีอยู่แล้วเพื่อทําลายข้อมูลของนักวิเคราะห์ข้อมูลทั่วโลก อย่างไรก็ตามเชื่อหรือไม่ไฟร์วอลล์ทําหน้าที่เพื่อวัตถุประสงค์ที่สําคัญ ในบทความนี้ เราจะเจาะลึกในประทุนเพื่อทําความเข้าใจวิธีการทํางานได้ดียิ่งขึ้น ด้วยความเข้าใจที่มากขึ้นคุณจะหวังว่าจะสามารถวินิจฉัยและแก้ไขข้อผิดพลาดของไฟร์วอลล์ได้ดีขึ้นในอนาคต
นี่อะไรน่ะ
วัตถุประสงค์ของไฟร์วอลล์ความเป็นส่วนตัวของข้อมูลนั้นง่าย: มีเพื่อป้องกันไม่ให้ Power Query จากการรั่วไหลของข้อมูลระหว่างแหล่งข้อมูลโดยไม่ได้ตั้งใจ
เหตุใดจึงจำเป็น ฉันหมายถึง คุณสามารถสร้าง M บางตัวที่จะส่งผ่านค่า SQL ไปยังตัวดึงข้อมูล OData ได้ แต่นี่อาจเป็นการรั่วไหลของข้อมูลอย่างตั้งใจ ผู้เขียน Mashup จะ (หรืออย่างน้อยก็ควร) รู้ว่าพวกเขากําลังทําเช่นนี้ เหตุใดความจําเป็นในการป้องกันการรั่วไหลของข้อมูลโดยไม่ได้ตั้งใจ
คําตอบ? พับ
พับ
การ พับเป็นคําที่อ้างถึงการแปลงนิพจน์ใน M (เช่น ตัวกรอง เปลี่ยนชื่อ การรวม และอื่นๆ) ให้เป็นการดําเนินการกับแหล่งข้อมูลดิบ (เช่น SQL, OData และอื่นๆ) ส่วนสําคัญของพลังของ Power Query มาจากข้อเท็จจริงที่ว่า PQ สามารถแปลงการดําเนินการที่ผู้ใช้ดําเนินการผ่านส่วนติดต่อผู้ใช้เป็น SQL ที่ซับซ้อนหรือภาษาแหล่งข้อมูล Backend อื่น ๆ โดยที่ผู้ใช้ไม่จําเป็นต้องรู้ภาษาดังกล่าว ผู้ใช้จะได้รับประโยชน์ด้านประสิทธิภาพการทํางานของการดําเนินการแหล่งข้อมูลแบบเนทีฟ ด้วย UI ที่ใช้งานง่ายซึ่งสามารถแปลงแหล่งข้อมูลทั้งหมดได้โดยใช้ชุดคําสั่งทั่วไป
ในฐานะที่เป็นส่วนหนึ่งของการพับ PQ บางครั้งอาจกําหนดว่าวิธีที่มีประสิทธิภาพที่สุดในการดําเนินการ mashup ที่กําหนดคือการนําข้อมูลจากแหล่งหนึ่งและส่งผ่านไปยังอีกแหล่งหนึ่ง ตัวอย่างเช่น หากคุณเข้าร่วมไฟล์ CSV ขนาดเล็กกับตาราง SQL ขนาดใหญ่ คุณอาจไม่ต้องการให้ PQ อ่านไฟล์ CSV อ่านตาราง SQL ทั้งหมดแล้วรวมเข้าด้วยกันบนคอมพิวเตอร์ของคุณ คุณอาจต้องการให้ PQ อินไลน์ข้อมูล CSV ลงในคําสั่ง SQL และขอให้ฐานข้อมูล SQL ดําเนินการรวม
นี่คือการรั่วไหลของข้อมูลที่ไม่ได้ตั้งใจเกิดขึ้น
ลองจินตนาการว่าคุณกําลังเข้าร่วมข้อมูล SQL ที่รวมหมายเลขประกันสังคมของพนักงานด้วยผลลัพธ์ของตัวดึงข้อมูล OData ภายนอก และคุณพบว่าหมายเลขประกันสังคมจาก SQL ถูกส่งไปยังบริการ OData อย่างฉับพลัน ข่าวร้ายใช่ไหม?
นี่คือประเภทของสถานการณ์ที่ไฟร์วอลล์มีวัตถุประสงค์เพื่อป้องกัน
ทํางานอย่างไร
ไฟร์วอลล์มีอยู่แล้วเพื่อป้องกันไม่ให้ข้อมูลจากแหล่งข้อมูลหนึ่งถูกส่งไปยังแหล่งอื่นโดยไม่ได้ตั้งใจ ง่ายพอ
แล้วมันทําภารกิจนี้ให้สําเร็จได้อย่างไร
ทําสิ่งนี้โดยการแบ่งคิวรี M ของคุณออกเป็นสิ่งที่เรียกว่าพาร์ติชันและบังคับใช้กฎต่อไปนี้:
- พาร์ติชันอาจเข้าถึงแหล่งข้อมูลที่เข้ากันได้ หรืออ้างอิงพาร์ติชันอื่น ๆ แต่ไม่ใช่ทั้งสองอย่าง
ง่าย แต่สับสน พาร์ติชันคืออะไร อะไรทําให้แหล่งข้อมูลสองแหล่ง "เข้ากันได้"? และทําไมไฟร์วอลล์ควรดูแลหากพาร์ติชั่นต้องการเข้าถึงแหล่งข้อมูลและอ้างอิงพาร์ติชัน?
เรามาดูกฎข้อนี้ทีละข้อกัน
พาร์ติชันคืออะไร
ในระดับพื้นฐานที่สุด พาร์ติชันเป็นเพียงคอลเลกชันของขั้นตอนคิวรีอย่างน้อยหนึ่งรายการ พาร์ติชันที่ละเอียดที่สุดที่เป็นไปได้ (อย่างน้อยในการใช้งานปัจจุบัน) เป็นขั้นตอนเดียว บางครั้งพาร์ติชันที่ใหญ่ที่สุดอาจครอบคลุมหลายคิวรีได้ (เพิ่มเติมเกี่ยวกับเรื่องนี้ในภายหลัง)
ถ้าคุณไม่คุ้นเคยกับขั้นตอน คุณสามารถดูขั้นตอนเหล่านั้นทางด้านขวาของหน้าต่าง ตัวแก้ไข Power Query หลังจากเลือกคิวรีในบานหน้าต่าง ขั้นตอนที่ใช้ ขั้นตอนติดตามทุกสิ่งที่คุณทําเพื่อแปลงข้อมูลของคุณให้เป็นรูปร่างสุดท้าย
พาร์ติชันที่อ้างอิงถึงพาร์ติชันอื่น
เมื่อมีการประเมินคิวรีด้วยไฟร์วอลล์ ไฟร์วอลล์จะแบ่งคิวรีและการอ้างอิงทั้งหมดเป็นพาร์ติชัน (นั่นคือกลุ่มของขั้นตอน) เมื่อใดก็ตามที่พาร์ติชันหนึ่งอ้างอิงบางอย่างในพาร์ติชันอื่น ไฟร์วอลล์จะแทนที่การอ้างอิงด้วยการเรียกไปยังฟังก์ชันพิเศษที่เรียกว่าValue.Firewall
กล่าวอีกนัยหนึ่งไฟร์วอลล์ไม่อนุญาตให้พาร์ติชันสามารถเข้าถึงซึ่งกันและกันได้โดยตรง การอ้างอิงทั้งหมดจะถูกแก้ไขเพื่อให้ผ่านไฟร์วอลล์ คิดว่าไฟร์วอลล์เป็นเกทเตอร์ พาร์ติชันที่อ้างอิงพาร์ติชันอื่นต้องได้รับสิทธิ์ไฟร์วอลล์ในการดําเนินการดังกล่าว และไฟร์วอลล์จะควบคุมว่าจะอนุญาตให้มีข้อมูลที่อ้างอิงลงในพาร์ติชันหรือไม่
ทั้งหมดนี้อาจดูเป็นนามธรรมที่สวยดังนั้นเรามาดูตัวอย่างกัน
สมมติว่าคุณมีคิวรีที่เรียกว่า พนักงาน ซึ่งดึงข้อมูลบางอย่างจากฐานข้อมูล SQL สมมติว่าคุณมีคิวรีอื่น (EmployeesReference) ซึ่งเพียงแค่อ้างอิงถึงพนักงาน
shared Employees = let
Source = Sql.Database(…),
EmployeesTable = …
in
EmployeesTable;
shared EmployeesReference = let
Source = Employees
in
Source;
คิวรีเหล่านี้จะแบ่งออกเป็นสองพาร์ติชัน: หนึ่งสําหรับคิวรี Employees และอีกหนึ่งสําหรับคิวรี EmployeesReference (ซึ่งจะอ้างอิงพาร์ติชัน Employees) เมื่อประเมินด้วยไฟร์วอลล์บน คิวรีเหล่านี้จะถูกเขียนใหม่เช่นนั้น:
shared Employees = let
Source = Sql.Database(…),
EmployeesTable = …
in
EmployeesTable;
shared EmployeesReference = let
Source = Value.Firewall("Section1/Employees")
in
Source;
โปรดสังเกตว่าการอ้างอิงอย่างง่ายไปยังคิวรี พนักงาน ถูกแทนที่ด้วยการเรียก ไปยัง Value.Firewall
ซึ่งให้ชื่อเต็มของคิวรี พนักงาน
เมื่อประเมิน EmployeesReference การเรียก ไปยัง Value.Firewall("Section1/Employees")
จะถูกสกัดกั้นโดยไฟร์วอลล์ ซึ่งตอนนี้มีโอกาสในการควบคุมว่า (และวิธีการ) โฟลว์ข้อมูลที่ร้องขอไปยังพาร์ติชัน EmployeesReference หรือไม่ ซึ่งสามารถทําสิ่งต่าง ๆ ได้หลายวิธี: ปฏิเสธคําขอ บัฟเฟอร์ข้อมูลที่ร้องขอ (ซึ่งจะป้องกันไม่ให้มีการพับไปยังแหล่งข้อมูลต้นฉบับเพิ่มเติม) และอื่น ๆ
นี่คือวิธีที่ไฟร์วอลล์รักษาการควบคุมการไหลของข้อมูลระหว่างพาร์ติชัน
พาร์ติชันที่เข้าถึงแหล่งข้อมูลโดยตรง
สมมติว่าคุณกําหนดคิวรี 1 ด้วยขั้นตอนเดียว (โปรดทราบว่าคิวรีแบบขั้นตอนเดียวนี้สอดคล้องกับพาร์ติชันไฟร์วอลล์หนึ่งพาร์ติชัน) และขั้นตอนเดียวนี้เข้าถึงแหล่งข้อมูลสองแหล่ง: ตารางฐานข้อมูล SQL และไฟล์ CSV ไฟร์วอลล์จัดการกับสิ่งนี้ได้อย่างไรเนื่องจากไม่มีการอ้างอิงพาร์ติชันและดังนั้นจึงไม่มีการเรียก Value.Firewall
ให้สกัดกั้น? เรามาทบทวนกฎที่ระบุไว้ก่อนหน้านี้:
- พาร์ติชันอาจเข้าถึงแหล่งข้อมูลที่เข้ากันได้ หรืออ้างอิงพาร์ติชันอื่น ๆ แต่ไม่ใช่ทั้งสองอย่าง
เพื่อให้คิวรีแหล่งข้อมูลแบบพาร์ติชันเดียวแต่สองแหล่งข้อมูลของคุณสามารถเรียกใช้ได้ แหล่งข้อมูลทั้งสองจะต้องเป็น "เข้ากันได้" กล่าวอีกนัยหนึ่ง จะต้องสามารถแชร์ข้อมูลแบบสองทิศทางระหว่างกันได้ ซึ่งหมายความว่าระดับความเป็นส่วนตัวของแหล่งข้อมูลทั้งสองจะต้องเป็นสาธารณะหรือทั้งสองอย่างเป็นองค์กร เนื่องจากทั้งสองอย่างนี้เป็นสองชุดรวมกันที่อนุญาตให้แชร์ในทั้งสองทิศทางได้ ถ้าแหล่งข้อมูลทั้งสองถูกทําเครื่องหมายเป็น ส่วนตัว หรือมีการทําเครื่องหมายเป็น สาธารณะ และอีกแหล่งข้อมูลหนึ่งถูกทําเครื่องหมายว่า องค์กร หรือมีการทําเครื่องหมายโดยใช้การรวมกันของระดับความเป็นส่วนตัวบางอย่าง การแชร์แบบสองทิศทางจะไม่ได้รับอนุญาตและดังนั้นจึงไม่ปลอดภัยสําหรับพวกเขาที่จะประเมินทั้งสองอย่างในพาร์ติชันเดียวกัน การทําเช่นนี้จะหมายความว่าการรั่วไหลของข้อมูลที่ไม่ปลอดภัยอาจเกิดขึ้นได้ (เนื่องจากการพับ) และไฟร์วอลล์จะไม่มีทางป้องกันได้
จะเกิดอะไรขึ้นถ้าคุณพยายามเข้าถึงแหล่งข้อมูลที่เข้ากันไม่ได้ในพาร์ติชันเดียวกัน
Formula.Firewall: Query 'Query1' (step 'Source') is accessing data sources that have privacy levels which cannot be used together. Please rebuild this data combination.
หวังว่าคุณจะเข้าใจหนึ่งในข้อความแสดงข้อผิดพลาดที่แสดงไว้ที่จุดเริ่มต้นของบทความนี้ได้ดียิ่งขึ้น
โปรดทราบว่าข้อกําหนดความเข้ากันได้นี้จะนําไปใช้ภายในพาร์ติชันที่ระบุเท่านั้น ถ้ามีการอ้างอิงพาร์ติชันอื่น ๆ แหล่งข้อมูลจากพาร์ติชันที่อ้างอิงไม่จําเป็นต้องเข้ากันได้กับอีกพาร์ติชันหนึ่ง ทั้งนี้เนื่องจากไฟร์วอลล์สามารถบัฟเฟอร์ข้อมูลได้ ซึ่งจะป้องกันการพับเพิ่มเติมใด ๆ กับแหล่งข้อมูลต้นฉบับ ข้อมูลจะถูกโหลดลงในหน่วยความจําและถือว่ามาจากที่ไหนเลย
ทําไมไม่ทําทั้งสองอย่าง
สมมติว่าคุณกําหนดคิวรีด้วยขั้นตอนหนึ่ง (ซึ่งจะสอดคล้องกับพาร์ติชันหนึ่ง) ที่เข้าถึงคิวรีอื่น ๆ สองรายการ (นั่นคือพาร์ติชันอื่นสองพาร์ติชัน) จะเกิดอะไรขึ้นถ้าคุณต้องการในขั้นตอนเดียวกันเพื่อเข้าถึงฐานข้อมูล SQL โดยตรงหรือไม่ ทําไมพาร์ติชันจึงไม่สามารถอ้างอิงพาร์ติชันอื่น ๆ และเข้าถึงแหล่งข้อมูลที่เข้ากันได้โดยตรง?
ขณะที่คุณเห็นก่อนหน้านี้ เมื่อพาร์ติชันหนึ่งอ้างอิงถึงพาร์ติชันอื่น ไฟร์วอลล์ทําหน้าที่เป็นตัวเก็บประตูสําหรับข้อมูลทั้งหมดที่ไหลเข้าไปในพาร์ติชัน เมื่อต้องการทําเช่นนั้น จะต้องสามารถควบคุมข้อมูลที่จะอนุญาตได้ หากมีการเข้าถึงแหล่งข้อมูลภายในพาร์ติชันและข้อมูลที่ไหลเข้ามาจากพาร์ติชันอื่น จะสูญเสียความสามารถในการเป็นผู้เฝ้าประตูเนื่องจากข้อมูลที่ไหลเข้ามาอาจรั่วไหลไปยังหนึ่งในแหล่งข้อมูลที่มีการเข้าถึงภายในโดยที่ไม่รู้ตัว ดังนั้นไฟร์วอลล์จะป้องกันพาร์ติชันที่เข้าถึงพาร์ติชันอื่น ๆ จากได้รับอนุญาตให้เข้าถึงแหล่งข้อมูลใด ๆ ได้โดยตรง
ดังนั้นจะเกิดอะไรขึ้นถ้าพาร์ติชันพยายามอ้างอิงพาร์ติชันอื่น ๆ และเข้าถึงแหล่งข้อมูลโดยตรง?
Formula.Firewall: Query 'Query1' (step 'Source') references other queries or steps, so it may not directly access a data source. Please rebuild this data combination.
ในตอนนี้ คุณหวังว่าจะเข้าใจข้อความแสดงข้อผิดพลาดอื่นๆ ที่แสดงอยู่ที่ส่วนเริ่มต้นของบทความนี้ได้ดียิ่งขึ้น
พาร์ติชันในเชิงลึก
ในขณะที่คุณสามารถคาดเดาจากข้อมูลข้างต้นวิธีการที่คิวรีจะถูกแบ่งพาร์ติชันจนมีความสําคัญอย่างไม่น่าเชื่อ ถ้าคุณมีบางขั้นตอนที่อ้างอิงคิวรีอื่นๆ และขั้นตอนอื่นๆ ที่เข้าถึงแหล่งข้อมูล ตอนนี้คุณหวังว่า การวาดขอบเขตของพาร์ติชันในบางที่จะทําให้เกิดข้อผิดพลาดของไฟร์วอลล์ ในขณะที่การวาดในที่อื่นจะช่วยให้คิวรีของคุณทํางานได้ดี
ดังนั้นคิวรีจะได้รับการแบ่งพาร์ติชันอย่างไร
ส่วนนี้อาจเป็นสิ่งสําคัญที่สุดสําหรับการทําความเข้าใจสาเหตุที่คุณเห็นข้อผิดพลาดของไฟร์วอลล์ และทําความเข้าใจวิธีการแก้ไขปัญหาดังกล่าว (ถ้าเป็นไปได้)
นี่คือข้อมูลสรุประดับสูงของตรรกะการแบ่งพาร์ติชัน
- การแบ่งพาร์ติชันเริ่มต้น
- สร้างพาร์ติชันสําหรับแต่ละขั้นตอนในแต่ละคิวรี
- ระยะคงที่
- ระยะนี้ไม่ขึ้นอยู่กับผลลัพธ์การประเมิน แต่จะขึ้นอยู่กับวิธีการจัดโครงสร้างคิวรี
- การตัดแต่งพารามิเตอร์
- ตัดแต่งพาร์ติชันพารามิเตอร์ esque นั่นคือพาร์ติชันใดก็ตามที่:
- ไม่อ้างอิงพาร์ติชันอื่น
- ไม่ประกอบด้วยการเรียกฟังก์ชันใดๆ
- ไม่ใช่วงจร (นั่นคือไม่ได้อ้างอิงถึงตัวเอง)
- โปรดทราบว่า "ลบ" พาร์ติชันอย่างมีประสิทธิภาพรวมอยู่ในพาร์ติชันอื่น ๆ ที่อ้างอิง
- การตัดแต่งพาร์ติชันพารามิเตอร์ช่วยให้การอ้างอิงพารามิเตอร์ที่ใช้ภายในการเรียกใช้ฟังก์ชันแหล่งข้อมูล (ตัวอย่างเช่น
Web.Contents(myUrl)
) ทํางานแทนการขว้าง "พาร์ติชันไม่สามารถอ้างอิงแหล่งข้อมูลและขั้นตอนอื่น ๆ"
- ตัดแต่งพาร์ติชันพารามิเตอร์ esque นั่นคือพาร์ติชันใดก็ตามที่:
- การจัดกลุ่ม (คงที่)
- มีการผสานพาร์ติชันในลําดับการขึ้นต่อกันด้านล่าง ในพาร์ติชันที่ผสานผลลัพธ์ รายการต่อไปนี้จะต้องแยกกัน:
- พาร์ติชันในคิวรีที่แตกต่างกัน
- พาร์ติชันที่ไม่ได้อ้างอิงพาร์ติชันอื่น ๆ (และได้รับอนุญาตให้เข้าถึงแหล่งข้อมูล)
- พาร์ติชันที่อ้างอิงถึงพาร์ติชันอื่น ๆ (และ จึงถูกห้ามไม่ให้เข้าถึงแหล่งข้อมูล)
- มีการผสานพาร์ติชันในลําดับการขึ้นต่อกันด้านล่าง ในพาร์ติชันที่ผสานผลลัพธ์ รายการต่อไปนี้จะต้องแยกกัน:
- การตัดแต่งพารามิเตอร์
- ระยะนี้ไม่ขึ้นอยู่กับผลลัพธ์การประเมิน แต่จะขึ้นอยู่กับวิธีการจัดโครงสร้างคิวรี
- ระยะแบบไดนามิก
- ระยะนี้ขึ้นอยู่กับผลลัพธ์การประเมิน รวมถึงข้อมูลเกี่ยวกับแหล่งข้อมูลที่เข้าถึงโดยพาร์ติชันต่างๆ
- การตัดแต่ง
- ตัดแต่งพาร์ติชันที่ตรงตามความต้องการต่อไปนี้ทั้งหมด:
- ไม่สามารถเข้าถึงแหล่งข้อมูลใด ๆ
- ไม่อ้างอิงพาร์ติชันใดๆ ที่เข้าถึงแหล่งข้อมูล
- ไม่ใช่วงจร
- ตัดแต่งพาร์ติชันที่ตรงตามความต้องการต่อไปนี้ทั้งหมด:
- การจัดกลุ่ม (แบบไดนามิก)
- ในตอนนี้พาร์ติชันที่ไม่จําเป็นได้ถูกตัดแต่งแล้ว ให้ลองสร้างพาร์ติชันแหล่งข้อมูลที่มีขนาดใหญ่ที่สุดเท่าที่เป็นไปได้ ซึ่งสามารถทําได้โดยการผสานพาร์ติชันโดยใช้กฎเดียวกันที่อธิบายไว้ในขั้นตอนการจัดกลุ่มแบบคงที่ด้านบน
ทั้งหมดนี้หมายความว่าอย่างไร
ลองทําตามตัวอย่างเพื่อแสดงตัวอย่างวิธีการทํางานของตรรกะที่ซับซ้อนที่วางไว้ด้านบน
นี่คือตัวอย่างสถานการณ์ ซึ่งเป็นการผสานแฟ้มข้อความ (ผู้ติดต่อ) ที่มีฐานข้อมูล SQL (พนักงาน) อย่างเป็นธรรม โดยที่เซิร์ฟเวอร์ SQL เป็นพารามิเตอร์ (DbServer)
คิวรีสามรายการ
นี่คือรหัส M สําหรับคิวรีสามรายการที่ใช้ในตัวอย่างนี้
shared DbServer = "MySqlServer" meta [IsParameterQuery=true, Type="Text", IsParameterQueryRequired=true];
shared Contacts = let
Source = Csv.Document(File.Contents("C:\contacts.txt"),[Delimiter=" ", Columns=15, Encoding=1252, QuoteStyle=QuoteStyle.None]),
#"Promoted Headers" = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),
#"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers",{{"ContactID", Int64.Type}, {"NameStyle", type logical}, {"Title", type text}, {"FirstName", type text}, {"MiddleName", type text}, {"LastName", type text}, {"Suffix", type text}, {"EmailAddress", type text}, {"EmailPromotion", Int64.Type}, {"Phone", type text}, {"PasswordHash", type text}, {"PasswordSalt", type text}, {"AdditionalContactInfo", type text}, {"rowguid", type text}, {"ModifiedDate", type datetime}})
in
#"Changed Type";
shared Employees = let
Source = Sql.Databases(DbServer),
AdventureWorks = Source{[Name="AdventureWorks"]}[Data],
HumanResources_Employee = AdventureWorks{[Schema="HumanResources",Item="Employee"]}[Data],
#"Removed Columns" = Table.RemoveColumns(HumanResources_Employee,{"HumanResources.Employee(EmployeeID)", "HumanResources.Employee(ManagerID)", "HumanResources.EmployeeAddress", "HumanResources.EmployeeDepartmentHistory", "HumanResources.EmployeePayHistory", "HumanResources.JobCandidate", "Person.Contact", "Purchasing.PurchaseOrderHeader", "Sales.SalesPerson"}),
#"Merged Queries" = Table.NestedJoin(#"Removed Columns",{"ContactID"},Contacts,{"ContactID"},"Contacts",JoinKind.LeftOuter),
#"Expanded Contacts" = Table.ExpandTableColumn(#"Merged Queries", "Contacts", {"EmailAddress"}, {"EmailAddress"})
in
#"Expanded Contacts";
นี่คือมุมมองระดับสูงกว่า ที่แสดงการขึ้นต่อกัน
มาแบ่งพาร์ติชันกัน
เรามาย่อ/ขยายสักเล็กน้อยและรวมขั้นตอนในรูปภาพและเริ่มเดินผ่านตรรกะการแบ่งพาร์ติชัน นี่คือไดอะแกรมของคิวรีสามรายการ ที่แสดงพาร์ติชันไฟร์วอลล์เริ่มต้นเป็นสีเขียว โปรดสังเกตว่าแต่ละขั้นตอนเริ่มต้นในพาร์ติชันของตนเอง
ถัดไป เราจะตัดแต่งพาร์ติชันพารามิเตอร์ ดังนั้น DbServer จะถูกรวมโดยนัยในพาร์ติชันต้นทาง
ในตอนนี้เราทําการจัดกลุ่มแบบคงที่ ซึ่งจะรักษาการแยกระหว่างพาร์ติชันในคิวรีที่แยกต่างหาก (หมายเหตุสําหรับอินสแตนซ์ที่สองขั้นตอนสุดท้ายของพนักงานจะไม่ได้รับการจัดกลุ่มตามขั้นตอนของผู้ติดต่อ) และระหว่างพาร์ติชันที่อ้างอิงพาร์ติชันอื่น ๆ (เช่น สองขั้นตอนสุดท้ายของพนักงาน) และส่วนที่ไม่ได้รวม (เช่น สามขั้นตอนแรกของพนักงาน)
ในตอนนี้เราเข้าสู่ระยะแบบไดนามิก ในระยะนี้ พาร์ติชันแบบคงที่ข้างต้นจะถูกประเมิน พาร์ติชันที่ไม่เข้าถึงแหล่งข้อมูลจะถูกตัดแต่ง จากนั้นพาร์ติชันจะถูกจัดกลุ่มเพื่อสร้างพาร์ติชันต้นทางที่มีขนาดใหญ่ที่สุดเท่าที่เป็นไปได้ อย่างไรก็ตาม ในสถานการณ์ตัวอย่างนี้ พาร์ติชันที่เหลือทั้งหมดจะเข้าถึงแหล่งข้อมูล และไม่มีการจัดกลุ่มเพิ่มเติมใด ๆ ที่สามารถทําได้ พาร์ติชันในตัวอย่างของเราจะไม่เปลี่ยนแปลงในระหว่างระยะนี้
มาเสแสร้งกัน
เพื่อให้ได้ภาพประกอบ แต่มาดูกันว่าจะเกิดอะไรขึ้นถ้าคิวรี Contacts แทนที่จะมาจากไฟล์ข้อความ โค้ดแบบฮาร์ดโค้ดใน M (อาจผ่าน กล่องโต้ตอบป้อนข้อมูล )
ในกรณีนี้ คิวรีผู้ติดต่อจะไม่เข้าถึงแหล่งข้อมูลใด ๆ ดังนั้นมันจะได้รับการตัดแต่งในช่วงแรกของระยะแบบไดนามิก
เมื่อลบพาร์ติชันผู้ติดต่อแล้ว สองขั้นตอนสุดท้ายของพนักงานจะไม่อ้างอิงพาร์ติชันใด ๆ อีกต่อไป ยกเว้นพาร์ติชันที่มีสามขั้นตอนแรกของพนักงาน ดังนั้น จะมีการจัดกลุ่มสองพาร์ติชัน
พาร์ติชันผลลัพธ์จะมีลักษณะดังนี้
ตัวอย่าง: การส่งผ่านข้อมูลจากแหล่งข้อมูลหนึ่งไปยังอีกแหล่งข้อมูลหนึ่ง
โอเค พอคําอธิบายที่เป็นนามธรรมแล้ว มาดูสถานการณ์ทั่วไปที่คุณมีแนวโน้มที่จะพบข้อผิดพลาดของไฟร์วอลล์และขั้นตอนในการแก้ไข
ลองจินตนาการว่าคุณต้องการค้นหาชื่อบริษัทจากบริการ Northwind OData จากนั้นใช้ชื่อบริษัทเพื่อทําการค้นหาใน Bing
ก่อนอื่น คุณสร้าง การสอบถาม Company เพื่อดึงข้อมูลชื่อบริษัท
let
Source = OData.Feed("https://services.odata.org/V4/Northwind/Northwind.svc/", null, [Implementation="2.0"]),
Customers_table = Source{[Name="Customers",Signature="table"]}[Data],
CHOPS = Customers_table{[CustomerID="CHOPS"]}[CompanyName]
in
CHOPS
ถัดไป คุณสร้าง คิวรีการค้นหา ที่อ้างอิง ถึงบริษัท และส่งผ่านไปยัง Bing
let
Source = Text.FromBinary(Web.Contents("https://www.bing.com/search?q=" & Company))
in
Source
ในตอนนี้ คุณพบปัญหา การประเมิน การค้นหา สร้างข้อผิดพลาดของไฟร์วอลล์
Formula.Firewall: Query 'Search' (step 'Source') references other queries or steps, so it may not directly access a data source. Please rebuild this data combination.
ทั้งนี้เนื่องจากขั้นตอนแหล่งที่มาของ การค้นหา จะอ้างอิงแหล่งข้อมูล (bing.com) และยังอ้างอิงคิวรี/พาร์ติชันอื่น (บริษัท) ซึ่งจะละเมิดกฎที่กล่าวถึงข้างต้น ("พาร์ติชันอาจเข้าถึงแหล่งข้อมูลที่เข้ากันได้ หรืออ้างอิงพาร์ติชันอื่น ๆ แต่ไม่ใช่ทั้งสองพาร์ติชัน")
สิ่งที่ต้องทํา? ตัวเลือกหนึ่งคือการปิดใช้งานไฟร์วอลล์ทั้งหมด (ผ่านตัวเลือกความเป็นส่วนตัวที่มี ป้ายชื่อละเว้นระดับความเป็นส่วนตัวและอาจปรับปรุงประสิทธิภาพการทํางาน) แต่จะเกิดอะไรขึ้นถ้าคุณต้องการออกจากไฟร์วอลล์ที่เปิดใช้งาน
หากต้องการแก้ไขข้อผิดพลาดโดยไม่ปิดใช้งานไฟร์วอลล์ คุณสามารถรวม Company และ Search ไว้ในคิวรีเดียวได้ ดังนี้:
let
Source = OData.Feed("https://services.odata.org/V4/Northwind/Northwind.svc/", null, [Implementation="2.0"]),
Customers_table = Source{[Name="Customers",Signature="table"]}[Data],
CHOPS = Customers_table{[CustomerID="CHOPS"]}[CompanyName],
Search = Text.FromBinary(Web.Contents("https://www.bing.com/search?q=" & CHOPS))
in
Search
ตอนนี้ทุกอย่างเกิดขึ้นภายในพาร์ติชันเดียว สมมติว่าระดับความเป็นส่วนตัวสําหรับแหล่งข้อมูลสองแหล่งสามารถเข้ากันได้ ตอนนี้ไฟร์วอลล์ควรมีความพอใจ และคุณจะไม่ได้รับข้อผิดพลาดอีกต่อไป
แค่ห่อ
แม้ว่าจะมีสิ่งอื่นอีกมากมายที่สามารถพูดได้ในหัวข้อนี้ บทความเกริ่นนํานี้มีความยาวพอแล้ว หวังว่าจะช่วยให้คุณเข้าใจไฟร์วอลล์ได้ดียิ่งขึ้นและจะช่วยให้คุณเข้าใจและแก้ไขข้อผิดพลาดของไฟร์วอลล์เมื่อคุณพบไฟร์วอลล์ในอนาคต