ฉันชื่อยาคูปอฟ อาซัต ฉันเป็นสถาปนิกข้อมูล และนี่คือความต่อเนื่องของตำนานประเภทตารางใน PostgreSQL ในส่วนนี้ เราจะพูดถึงตารางแบบคลัสเตอร์และตารางต่างประเทศ มาดูตัวอย่างการสร้างสรรค์ ขอบเขตการใช้งาน และข้อดีข้อเสียของการใช้งานกัน
ตารางคลัสเตอร์ใน PostgreSQL
ใน PostgreSQL ตารางคลัสเตอร์คือตารางที่มีการเปลี่ยนแปลงลำดับทางกายภาพของแถวเพื่อให้ตรงกับลำดับของแถวในดัชนี สิ่งนี้แตกต่างจากพฤติกรรมปกติของตาราง โดยที่ลำดับทางกายภาพของแถวอาจไม่ตรงกับลำดับของแถวตามที่กำหนดโดยดัชนีใดๆ
ไม่กี่คนที่ชอบความวุ่นวาย ทุกคนชอบความสงบ ภายในกรอบของฐานข้อมูลเชิงสัมพันธ์ แนวคิดเรื่องความสับสนวุ่นวายนั้นเชื่อมโยงอย่างใกล้ชิดกับการจัดเก็บข้อมูล เนื่องจากตลอดวงจรชีวิตของตารางมีการเปลี่ยนแปลงอยู่ตลอดเวลา
ในกระบวนการทำงานกับ DBMS ในระดับดิสก์ เนื้อหาของตารางจะเปลี่ยนแปลงอยู่ตลอดเวลา ตัวอย่างเช่น คุณได้อัปเดตข้อมูลแล้ว และแถวที่อัปเดตของคุณไปอยู่ในอีกหน้าหนึ่งของตาราง (ในที่นี้เราควรพูดถึง "FILLFACTOR") โดยมีทูเพิลที่ไม่ทำงานในตำแหน่งปัจจุบัน จากนั้นกระบวนการดูดอัตโนมัติจะลบทูเพิลที่ตายแล้วออก และช่องที่ว่างก็เต็มไปด้วยแถวที่ได้รับใหม่
แบบทดสอบง่ายๆ ที่คุณเองก็ทำได้ สร้างคำสั่งต่อไปนี้ลงในตารางที่สร้างขึ้นใหม่ตามปกติ:
INSERT INTO test(id,name) VALUES(1, ‘Peter’); INSERT INTO test(id,name) VALUES(2, ‘Ivan’); INSERT INTO test(id,name) VALUES(3, ‘Sergey’);
หลังจากดำเนินการค้นหา SQL (โปรดทราบว่าไม่มี ORDER BY
):
SELECT * FROM test;
คุณจะเห็นภาพที่คาดหวัง:
แต่ด้วยการทำการอัพเดตแถว
UPDATE test SET name = ‘Ruslan’ WHERE id = 2;
จากนั้นเมื่อรัน SQL เดียวกัน คุณจะได้รับ:
ลำดับแถวเปลี่ยนไป! เอนโทรปีได้เติบโตขึ้น
ทีนี้ลองจินตนาการว่าคุณกำลังมองหาข้อมูลในตาราง เช่น หมายเลข 4 คุณจะทำสิ่งนี้ภายในโทโพโลยีสีเขียวที่วุ่นวายที่ฉันวาดไว้ด้านล่างซ้ายได้อย่างไร แค่อ่านบันทึกแล้วบันทึกเล่า: คุณเผลอไปกดตัวเลขบางตัวแล้วเปรียบเทียบกับเลข 4 ที่ต้องการ อันที่จริง คุณจะต้องผ่านรายการทั้งหมด เพราะอาจมีเลข 4 มากกว่าหนึ่งตัว กล่าวอีกนัยหนึ่ง จำเป็นต้องมีการสแกนตามลำดับ
แต่เมื่อคุณมีลำดับ ดังในตารางทางด้านขวา คุณจะรู้ได้อย่างชัดเจนว่าเลข 4 อยู่ระหว่าง 3 ถึง 5 นั่นคือจุดรวมของการจัดระเบียบลำดับและตารางแบบคลัสเตอร์: พวกมันช่วยสร้างโครงสร้างที่ได้รับคำสั่งให้ปราศจากความสับสนวุ่นวาย หากคุณสุ่มเลือกตำแหน่งสุ่มในตารางสีน้ำเงินตามลำดับเพื่อค้นหาหมายเลข 4 ผลลัพธ์ที่เป็นไปได้สามประการ:
- จำนวนเท่ากับจำนวนที่ต้องการ
- จำนวนน้อยกว่าที่ต้องการ
- จำนวนมากกว่าที่ต้องการ
สิ่งนี้ให้ข้อได้เปรียบอย่างมากในเรื่องความเร็วในการดำเนินการค้นหา หากตัวเลขมากกว่า 4 คุณจะค้นหาตารางต่อไป ถ้าน้อยก็ลง หรือคุณสามารถหาช่วงและค้นหาหมายเลข 4 ที่อยู่ข้างในได้ ซึ่งเร็วกว่าการค้นหาข้อมูลทั้งหมดมาก เนื่องจากอยู่ในโทโพโลยีสีเขียวที่ไม่มีการรวบรวมกัน กล่าวคือ ลอการิทึมคูณเร็วกว่า
ลองพิจารณาตัวอย่างการสร้างตารางแบบคลัสเตอร์:
CREATE TABLE test.cluster_table (id INTEGER, name VARCHAR) WITH (FILLFACTOR = 90); CREATE INDEX id_idx ON test.cluster_table (id); CLUSTER [VERBOSE] test.cluster_table USING id_idx;
ที่นี่ฉันสร้างตารางชื่อ cluster_table
และตั้งค่า FILLFACTOR
เป็น 90% นี่คือเปอร์เซ็นต์การเติม ไม่มีผลกระทบต่อตารางคลัสเตอร์ของเราแต่อย่างใด นี่เป็นเพียงตัวอย่างวิธีตั้งค่าคุณสมบัติเมื่อสร้างตารางประเภทนี้ ต่อไป ฉันสร้างดัชนี BTree บนตาราง (CREATE INDEX
) ในช่อง id และเรียกใช้คำสั่ง CLUSTER
คำสั่ง CLUSTER
ทำการจัดกลุ่มตารางโดยใช้ดัชนีที่เราสร้างไว้ก่อนหน้านี้
สิ่งสำคัญคือต้องทราบที่นี่ว่าจนกว่าการทำคลัสเตอร์จะเสร็จสิ้น ธุรกรรมปัจจุบันทั้งหมดในตารางจะถูกบล็อก การบล็อกการรับส่งข้อมูลเกิดขึ้นเนื่องจาก Postgres พยายามสร้างตารางใหม่ตามลำดับที่คุณต้องการโดยอิงจากดัชนี และหลังจากสร้างคำสั่งซื้อนี้แล้ว Postgres ควรบันทึกลงในไฟล์อื่น
อันที่จริง นี่คือการดำเนินการย้ายข้อมูลระดับดิสก์จากไฟล์หนึ่งไปยังอีกไฟล์หนึ่ง แต่จะอยู่ในลำดับที่ระบุเท่านั้น ข้อมูลควรวางตามดัชนี ในกรณีของเราโดยช่องรหัส ฉันได้แสดงสิ่งนี้ในรูปแบบกราฟิกด้านล่างโดยอ้างอิงถึงข้อมูลเมตาก่อนและหลังการจัดกลุ่มของตาราง
เริ่มแรกตารางถูกวางไว้ในไฟล์หมายเลข 45969 หลังจากคำสั่ง CLUSTER
ชื่อไฟล์ก็เปลี่ยนไป ข้อมูลถูกย้ายจากไฟล์หนึ่งไปยังอีกไฟล์หนึ่ง ดังนั้น การบล็อกจึงเกิดขึ้น และด้วยเหตุนี้ การรับส่งข้อมูลขาเข้าจึงไม่สามารถใช้ตารางนี้ได้จนกว่าจะพร้อมใช้งาน
คุณยังสามารถสร้างดัชนีสำหรับการจัดกลุ่มในภายหลังที่มีหลายคอลัมน์ (ดัชนีหลายคอลัมน์) หรือระบุลำดับจากมากไปน้อยสำหรับบางคอลัมน์ (DESC / ASC)
คุณสามารถเลือกใช้คำสั่ง CLUSTER VERBOSE
ซึ่งจะส่งกลับรายละเอียดว่า PostgreSQL ทำอะไรบ้าง เช่น มีกี่เพจ เพจไหนถูกย้าย และอื่นๆ
กรณีทดสอบและลำดับข้อมูล
มาทำแบบทดสอบกันหน่อย:
CREATE TABLE test.cluster_table (id INTEGER, name VARCHAR) WITH (FILLFACTOR = 90); CREATE INDEX id_idx ON test.cluster_table (id); INSERT INTO test.cluster_table SELECT (random( )*100)::INTEGER, 'test' FROM generate_series(1,100) AS g(i); SELECT id FROM test.cluster_table;
มาสร้างตาราง โดยสร้างดัชนีตามช่อง id จากนั้นสร้าง 100 แถวตามต้องการโดยใช้คำสั่ง Generate_series ผลลัพธ์คือข้อมูลที่ไม่เรียงลำดับ:
เพื่อให้ผลลัพธ์มีลำดับ เราต้องเพิ่มคีย์เวิร์ด ORDER BY
แต่สิ่งสำคัญคือต้องจำไว้ว่าการดำเนินการ ORDER BY
ต้องใช้ทรัพยากรด้วย และคุณควรจ่ายเงินเพื่อดำเนินการดังกล่าว ทุก ๆ นาโนวินาทีจะมีปริมาณการรับส่งข้อมูลสูง จากนั้นจะมีการเรียงลำดับ
ในกรณีนี้ เรามาทำคลัสเตอร์ตารางด้วยคำสั่ง CLUSTER VERBOSE
โดยใช้ดัชนีที่ฉันสร้างไว้ล่วงหน้า:
CLUSTER VERBOSE test.cluster_table USING id_idx; SELECT id FROM test.cluster_table;
Voila ข้อมูลจะถูกจัดเรียงโดยไม่เรียงลำดับ:
แต่มีกับดักอยู่ที่นี่ มาอัปเดตแถวทั้งหมดกัน แต่จริงๆ แล้ว เปลี่ยนค่าของแถวเดียวก็เพียงพอแล้ว
UPDATE test.cluster_table SET id = id * (random( )::INTEGER); SELECT id FROM test.cluster_table;
ในกรณีนี้ ความโกลาหลจะกลับมาที่ตารางคลัสเตอร์ของเรา:
หากต้องการคืนค่าคำสั่งซื้อ คุณจะต้องเรียกใช้คำสั่ง CLUSTER
อีกครั้ง คุณไม่จำเป็นต้องระบุดัชนีอีกครั้ง เนื่องจากดัชนีจะยังคงอยู่ในข้อมูลเมตาของ PostgreSQL และฐานข้อมูลจะเข้าใจในครั้งต่อไปว่าคุณกำลังทำคลัสเตอร์อะไร
CLUSTER VERBOSE test.cluster_table; SELECT id FROM test.cluster_table;
คุณจะสามารถสังเกตลำดับได้อีกครั้งหลังจากคำสั่ง CLUSTER
เท่านั้น นี่คือจุดอ่อนของตารางแบบคลัสเตอร์: การเปลี่ยนแปลงใดๆ ในคีย์การจัดกลุ่มสามารถนำมาซึ่งความไม่เป็นระเบียบให้กับข้อมูลได้ทันที
เมื่อตารางคลัสเตอร์มีความเหมาะสม
ตารางแบบคลัสเตอร์จะเหมาะสมหากข้อมูลของคุณเป็นตารางอ้างอิง (ดี หรือ SCD — ขนาดที่เปลี่ยนแปลงช้าๆ) เช่น ระบบที่อยู่ ตารางประเภทนี้จะสะดวกหากคุณอัปโหลดข้อมูลใหม่ไม่บ่อยนัก เช่น เดือนละครั้ง
หากตารางเปลี่ยนแปลงบ่อยมากและอยู่ภายใต้การดำเนินการ INSERT
, UPDATE
และ DELETE
ก็จะต้องมีการรวมกลุ่มอย่างต่อเนื่อง ซึ่งไม่สะดวกและมีความสำคัญโดยทั่วไป วัตถุประสงค์ของการทำคลัสเตอร์คือการหลีกเลี่ยง ORDER BY
ที่ไม่จำเป็นในการสืบค้นตารางอย่างต่อเนื่องโดยฟิลด์หรือฟิลด์ที่คลัสเตอร์
ข้อมูลเมตาของตารางคลัสเตอร์
จากข้อมูลเมตาของตารางแบบคลัสเตอร์ คุณจะเข้าใจได้ว่าตารางเป็นแบบคลัสเตอร์:
SELECT c.oid AS “OID”, c.relname AS “Relation name” FROM pg_class c INNER JOIN pg_index i ON i.indrelid = c.oid WHERE c.relkind = ‘r’ AND c.relhasindex AND i.indisclustered;
ค่า "จริง" ในช่อง relhasindex
บ่งชี้ว่ามีดัชนีที่รองรับการจัดกลุ่ม เมื่อเราสร้างคลัสเตอร์ใหม่ในคำสั่ง CLUSTER
ถัดไป PostgreSQL จะใช้ดัชนีที่ระบุจากข้อมูลเมตา
ตารางต่างประเทศใน PostgreSQL
ตารางต่างประเทศใน PostgreSQL คือตารางที่เก็บอยู่นอกฐานข้อมูล ตารางเหล่านี้สามารถอยู่บนเซิร์ฟเวอร์ฐานข้อมูลอื่นหรือในไฟล์ได้ เป็นต้น ตารางต่างประเทศมีประโยชน์ในแง่ของการรับข้อมูลจากแหล่งอื่นอย่างรวดเร็ว หากคุณมีความสามารถในการเข้าร่วม
นอกจากนี้ หากคุณปรับเปลี่ยน คุณสามารถจัดเตรียมสิ่งที่เรียกว่าวงจรชีวิตข้อมูลเพื่อจัดเตรียมตัววัดนโยบายการเก็บรักษาได้ ชุดเครื่องมือต่อไปนี้สามารถช่วยคุณได้ที่นี่:
- ดู (ตารางเสมือน)
- ชุดตารางปกติที่คั่นด้วยตรรกะการเก็บข้อมูล (การออกแบบ POOD) พร้อมข้อมูลล่าสุด
- ตารางต่างประเทศที่เน้นไปที่ไฟล์ที่จัดเก็บข้อมูลนอกฐานข้อมูลบนดิสก์ราคาถูก (ที่นี่คุณจะพบข้อมูลเก่าที่เกินเกณฑ์ชี้วัดนโยบายการเก็บรักษา)
มีตารางและประเภทการเชื่อมต่อต่างประเทศมากมาย เช่น:
- ไฟล์ CSV
- การเชื่อมต่อกับ RDBMS อื่น ๆ อีกมากมาย
- การเชื่อมต่อกับฐานข้อมูล NoSQL บางส่วน
มาดูตัวอย่างตารางต่างประเทศที่ใช้ไฟล์ CSV กัน ส่วนขยาย file_fdw
ที่ใช้ fdw — wrapper ข้อมูลต่างประเทศ — จะช่วยเราในเรื่องนี้:
CREATE EXTENSION file_fdw; CREATE SERVER csv_log FOREIGN DATA WRAPPER file_fdw; CREATE FOREIGN TABLE test.csv ( id INTEGER, name VARCHAR ) SERVER csv_log OPTIONS (filename '/var/lib/postgresql/file.csv', delimiter ‘;', format 'csv');
ฉันสร้างตารางต่างประเทศและอธิบายคุณลักษณะโดยระบุเซิร์ฟเวอร์สำหรับ fdw ซึ่งฉันสร้างขึ้นล่วงหน้าพร้อมตัวเลือกสำหรับการทำงานกับไฟล์
หากฉันสร้างแบบสอบถาม SQL ไปยังตารางต่างประเทศ ฉันจะเห็นข้อมูลที่แสดงในไฟล์ เนื่องจากมีการลงทะเบียนตารางต่างประเทศ (หมายความว่ามีรายการอยู่ในข้อมูลเมตาของ PostgreSQL) ฉันจึงมีสมมติฐาน: ข้อมูลไม่จัดเก็บไว้ในไฟล์ภายนอก แต่อยู่ในไฟล์ข้อมูล PostgreSQL หรือไม่
SELECT oid AS “OID”, pg_relation_filepath(oid) AS “File path”, pg_relation_size(oid) AS “Relation Size” FROM pg_class WHERE relname = ‘csv’;
ผลการดำเนินการ:
ดังนั้น ตารางภายนอกในฐานะออบเจ็กต์จะถูกลงทะเบียนในข้อมูลเมตา (มีตัวระบุ OID ของออบเจ็กต์) แต่ไม่มีไฟล์ข้อมูลที่เกี่ยวข้อง กล่าวคือ ข้อมูลจะถูกนำเสนอในแหล่งข้อมูลภายนอกเท่านั้น
แบบสอบถามไปยังตารางต่างประเทศ
แบบสอบถามไปยังตารางต่างประเทศทำงานอย่างไร ลองใช้ไฟล์ CSV เป็นตัวอย่าง
ในขณะที่ข้อมูลกำลังโหลด จะมีความล่าช้าค่อนข้างนาน ดังนั้นเราจึงจัดเก็บข้อมูลเก่าไว้ที่ใดที่หนึ่งในดิสก์เก่า ในการรับข้อมูล เราจำเป็นต้องเปิดตัวอธิบายไฟล์ภายนอก จากนั้นคัดลอกข้อมูลไปยังหน่วยความจำหรือไฟล์ชั่วคราว แล้วส่งข้อมูลกลับมาให้เรา หากเราดำเนินการคำขอเดิมอีกครั้งในภายหลังเล็กน้อย จะไม่มีการเร่งความเร็วใดๆ กระบวนการยังคงเหมือนเดิม
มีห้องสมุดโต๊ะต่างประเทศมากมายสำหรับความต้องการที่หลากหลาย ตัวอย่างเช่น postgres_fdw ด้วยความช่วยเหลือนี้ เราสามารถเชื่อมต่อกับ PostgreSQL จาก PostgreSQL ได้ มันเหมือนกับลิงค์ฐานข้อมูลมาก:
CREATE EXTENSION postgres_fdw; DROP FOREIGN TABLE test.csv; CREATE SERVER pg_log FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host '192.168.56.10', port '5432', dbname ‘course_db'); CREATE USER MAPPING FOR test SERVER pg_log OPTIONS (user 'test', password 'test'); CREATE FOREIGN TABLE test.csv ( id INTEGER, name VARCHAR ) SERVER pg_log OPTIONS (schema_name 'test', table_name ‘user');
มี "ไลบรารีจำนวนมาก" จำนวนมากสำหรับการทำงานกับแหล่งข้อมูลภายนอก ตัวอย่างเช่น:
- ออราเคิล, MySQL, SQLite, เซิร์ฟเวอร์ MS SQL, Sybase
- แคสแซนดรา, MongoBD, HBase, Redis, Neo4j
- ทวิตเตอร์, โทรเลข
- JSON, XLM, GeoFiles, LDAP
ข้อมูลเมตาของตารางต่างประเทศ
ตามที่เราค้นพบ ตารางที่แปลกในฐานะวัตถุได้รับการแก้ไขในข้อมูลเมตา:
SELECT oid AS "OID", relname AS “Relation name", CASE WHEN relpersistence = 'p' THEN 'Permanent' WHEN relpersistence = 't' THEN 'Temporary' ELSE 'Unlogged' END AS “Type”, relkind AS “Subtype” FROM pg_class WHERE relname = ‘csv’;
มันเป็นตารางถาวร (น่าประหลาดใจ) แต่มีตัวชี้ "f" ซึ่งเป็นประเภทย่อยของความสัมพันธ์ และมันบ่งบอกว่าโต๊ะของเราเป็นของต่างประเทศนั่นคือภายนอก
ในซีรีย์ต่อไป
นั่นคือทั้งหมดสำหรับวันนี้ เราจะวิเคราะห์ในเนื้อหาต่อไปนี้:
- ตารางที่แบ่งพาร์ติชัน
- ตารางที่สืบทอดมา