Cassandra ภาษาคำสั่งค้นหา (CQL): แทรก อัปเดต และลบ

⚡ สรุปอย่างชาญฉลาด

Cassandra ภาษาคิวรี (Query Language) จัดการการแทรก การอัปเดต การลบ และการอ่านข้อมูลด้วยไวยากรณ์ที่คล้ายกับ SQL แต่มีความหมายที่แตกต่างกันออกไป หน้านี้จะกล่าวถึงคำสั่งแต่ละคำสั่ง พฤติกรรมของคำสั่ง upsert ที่รวมการแทรกและการอัปเดตเข้าด้วยกัน และข้อจำกัดที่แท้จริงของเงื่อนไข WHERE

  • ใส่พฤติกรรม: เฉพาะคีย์หลักเท่านั้นที่จำเป็น และคอลัมน์ที่ไม่ได้ระบุจะไม่ใช้พื้นที่จัดเก็บข้อมูล
  • 🔄 ความหมายของการอัปเดตข้อมูล (Upsert Semetics): การแทรกและการอัปเดตเป็นการดำเนินการเดียวกัน ดังนั้นการเขียนคีย์ที่มีอยู่แล้วลงไปจะเขียนทับคีย์เดิมโดยไม่แจ้งให้ทราบล่วงหน้า
  • 🗑️ ลบค่าใช้จ่าย: แถวที่ถูกลบจะกลายเป็นเหมือนหลุมศพ และจะหายไปก็ต่อเมื่อการประมวลผลเสร็จสิ้นแล้วเท่านั้น
  • 🔍 ข้อจำกัดของข้อกำหนด: การกรองข้อมูลจะทำงานบนคอลัมน์คีย์หลัก หรือบนคอลัมน์อื่นๆ หากมีการสร้างดัชนีไว้แล้ว
  • 📊 การสนับสนุนโดยรวม: จำนวน, ค่าต่ำสุด, ค่าสูงสุด, ผลรวม, AVG และรองรับคำสั่ง GROUP BY แต่จะมีประสิทธิภาพเฉพาะภายในพาร์ติชันเดียวเท่านั้น
  • ???? ยังไม่ได้รับการสนับสนุน: ตามการออกแบบแล้ว การเชื่อมต่อ (Joins), เงื่อนไข OR และการวิเคราะห์ข้ามพาร์ติชันยังคงอยู่นอกเหนือขอบเขตของ CQL

Cassandra CQL แทรก อัปเดต ลบ

แทรกข้อมูล

การขอ Cassandra คำสั่ง insert เขียนข้อมูลลงไป Cassandra คอลัมน์ในรูปแบบแถว Cassandra แทรกแบบสอบถามจะเก็บเฉพาะคอลัมน์ที่ผู้ใช้กำหนดเท่านั้น คุณต้องระบุเฉพาะคอลัมน์คีย์หลักเท่านั้น

จะไม่ใช้พื้นที่ใดๆ สำหรับค่าที่ไม่ได้ระบุ ไม่มีผลลัพธ์ส่งคืนหลังจากการแทรก

วากยสัมพันธ์

INSERT INTO KeyspaceName.TableName (ColumnName1, ColumnName2, ColumnName3)
VALUES (Column1Value, Column2Value, Column3Value);

ตัวอย่าง

นี่คือภาพรวมของการดำเนินการ Cassandra แทรกลงในแบบสอบถามตารางที่จะแทรกหนึ่งระเบียนเข้าไป Cassandra ตาราง 'นักเรียน'

แทรกข้อมูล

INSERT INTO University.Student (RollNo, Name, dept, Semester)
VALUES (2, 'Michael', 'CS', 2);

หลังจากดำเนินการคำสั่ง Insert into สำเร็จแล้ว Cassandraจะมีการแทรกหนึ่งแถวใน Cassandra นักเรียนโต๊ะที่มี RollNo 2 ชื่อ Michael แผนก CS และภาคเรียนที่ 2

นี่คือภาพรวมของสถานะฐานข้อมูลปัจจุบัน

แทรกข้อมูล

อัปเปอร์ข้อมูล

Cassandra ไม่ทำให้อารมณ์เสีย อัปเปอร์หมายความว่าอย่างนั้น Cassandra จะแทรกแถวหากยังไม่มีคีย์หลัก มิฉะนั้น หากคีย์หลักมีอยู่แล้ว ระบบจะอัปเดตแถวนั้น

ผลกระทบในทางปฏิบัติที่ควรกล่าวถึงอย่างชัดเจนก็คือ คำสั่ง INSERT จะไม่รายงานข้อผิดพลาดเกี่ยวกับคีย์ซ้ำ ดังนั้นการแทรกข้อมูลซ้ำโดยไม่ได้ตั้งใจจะเขียนทับแถวที่มีอยู่โดยไม่มีการแจ้งเตือน เมื่อต้องการป้องกันเหตุการณ์ดังกล่าว ให้เพิ่ม IF NOT EXISTS เพื่อให้คำสั่งนั้นเป็นธุรกรรมที่มีขนาดเล็ก

INSERT INTO University.Student (RollNo, Name)
VALUES (2, 'Michael') IF NOT EXISTS;

ธุรกรรมแบบเบา (Lightweight transactions) ใช้กระบวนการตรวจสอบความเห็นพ้องต้องกันในหลายสำเนา ดังนั้นจึงช้ากว่าการเขียนข้อมูลแบบปกติมาก และควรใช้เฉพาะในกรณีที่จำเป็นต้องตรวจสอบอย่างแท้จริงเท่านั้น

อัปเดตข้อมูล

การขอ Cassandra Update query ใช้ในการอัพเดตข้อมูลใน Cassandra ตารางหากไม่มีผลลัพธ์ใดๆ กลับมาหลังจากอัปเดตข้อมูล แสดงว่าอัปเดตข้อมูลสำเร็จแล้ว มิฉะนั้นจะส่งคืนข้อผิดพลาด ค่าคอลัมน์จะเปลี่ยนแปลงในคำสั่ง 'Set' ในขณะที่ข้อมูลจะถูกกรองด้วยคำสั่ง 'Where'

วากยสัมพันธ์

UPDATE KeyspaceName.TableName
SET ColumnName1 = NewValue1,
    ColumnName2 = NewValue2
WHERE ColumnName = ColumnValue;

ตัวอย่าง

นี่คือภาพหน้าจอที่แสดงสถานะฐานข้อมูลก่อนที่จะอัปเดตข้อมูล

อัปเดตข้อมูล

นี่คือภาพรวมของการดำเนินการ Cassandra คำสั่ง Update ที่อัพเดตเรกคอร์ดในตาราง Student

อัปเดตข้อมูล

UPDATE University.Student
SET name = 'Hayden'
WHERE rollno = 1;

หลังจากดำเนินการค้นหาการอัปเดตสำเร็จแล้ว Cassandra 'อัปเดตนักศึกษา' ชื่อนักศึกษาจะเปลี่ยนจาก 'คลาร์ก' เป็น 'เฮย์เดน' ที่มีม้วนหมายเลข 1

นี่คือภาพหน้าจอที่แสดงสถานะฐานข้อมูลหลังจากอัปเดตข้อมูล

อัปเดตข้อมูล

เนื่องจากลักษณะการทำงานของคำสั่ง upsert การอัปเดตข้อมูลกับคีย์หลักที่ไม่มีอยู่จะสร้างแถวข้อมูลขึ้นมาแทนที่จะเกิดข้อผิดพลาด

Cassandra ลบข้อมูล

คำสั่ง 'Delete' จะลบทั้งแถวหรือบางคอลัมน์ออกจากตาราง Student เมื่อลบข้อมูลแล้วจะไม่ถูกลบออกจากตารางทันที ข้อมูลที่ถูกลบจะถูกทำเครื่องหมายด้วยหลุมฝังศพและจะถูกลบออกหลังจากการบดอัด

วากยสัมพันธ์

DELETE FROM KeyspaceName.TableName
WHERE ColumnName1 = ColumnValue;

ดังกล่าวข้างต้น Cassandra ลบไวยากรณ์แถวจะลบหนึ่งแถวขึ้นไปขึ้นอยู่กับการกรองข้อมูลในส่วนคำสั่งที่

DELETE ColumnName1, ColumnName2 FROM KeyspaceName.TableName
WHERE ColumnName1 = ColumnValue;

ไวยากรณ์ข้างต้นจะลบบางคอลัมน์ออกจากตาราง

ตัวอย่าง

นี่คือสแน็ปช็อตที่แสดงสถานะฐานข้อมูลปัจจุบันก่อนที่จะลบข้อมูล

Cassandra ลบข้อมูล

นี่คือภาพรวมของคำสั่งที่จะลบหนึ่งแถวออกจากตาราง Student

Cassandra ลบข้อมูล

DELETE FROM University.Student WHERE rollno = 1;

หลังจากดำเนินการคำสั่ง CQL Delete สำเร็จแล้ว จะมีการลบแถวหนึ่งแถวออกจากตาราง Student โดยที่ค่า rollno เป็น 1

นี่คือสแน็ปช็อตที่แสดงสถานะฐานข้อมูลหลังจากลบข้อมูล

Cassandra ลบข้อมูล

ข้อมูลที่ถูกลบจะคงอยู่เป็นเวลา gc_grace_seconds ซึ่งค่าเริ่มต้นคือสิบวัน เพื่อป้องกันไม่ให้โหนดที่ออฟไลน์ระหว่างการลบสามารถกู้คืนแถวนั้นได้เมื่อกลับมาทำงาน การลบข้อมูลจำนวนมากจึงทิ้งร่องรอยไว้ ซึ่งการอ่านข้อมูลในภายหลังทุกครั้งจะต้องสแกนผ่านไป

อะไร Cassandra ไม่สนับสนุน

CQL ยืมไวยากรณ์ของ SQL แต่ไม่ได้ใช้โมเดลการดำเนินการเชิงสัมพันธ์ ดังนั้นโครงสร้างที่คุ้นเคยหลายอย่างจึงทำงานแตกต่างออกไปหรือไม่มีให้ใช้งาน

  1. CQL ไม่รองรับการเชื่อมตาราง (join) ระหว่างตารางต่างๆ ข้อมูลที่เกี่ยวข้องจะต้องถูกแปลงเป็นรูปแบบที่ไม่ปกติ (denormalize) ให้รวมอยู่ในตารางเดียวในระหว่างการเขียนข้อมูล
  2. CQL ไม่รองรับเงื่อนไข OR ในส่วน WHERE ให้ใช้ IN กับคอลัมน์เดียว หรือเรียกใช้คำสั่งค้นหาแยกกัน
  3. CQL ไม่รองรับคำสั่ง UNION หรือ INTERSECT
  4. คอลัมน์ที่ไม่ใช่คีย์หลักจะไม่สามารถกรองได้จนกว่าจะมีดัชนีอยู่ในคอลัมน์นั้น
  5. การเปรียบเทียบมากกว่าและน้อยกว่านั้นใช้ได้เฉพาะกับคอลัมน์การจัดกลุ่มเท่านั้น เนื่องจากมีเพียงคอลัมน์เหล่านั้นเท่านั้นที่ได้รับการจัดเรียงในดิสก์
  6. การจับคู่รูปแบบด้วยคำสั่ง LIKE จำเป็นต้องใช้ดัชนี SASI และไม่สามารถใช้ได้กับคอลัมน์ทั่วไป

มีข้อกล่าวอ้างที่กล่าวกันมานานข้อหนึ่งที่ต้องแก้ไข คือ ฟังก์ชันการรวมข้อมูลได้รับการสนับสนุน: นับ, ค่าต่ำสุด, ค่าสูงสุด, ผลรวม และ AVG มาถึงแล้ว Cassandra 2.2 และ จัดกลุ่มตาม มาถึงในเวอร์ชัน 3.10 ข้อจำกัดอยู่ที่ขอบเขตมากกว่าความพร้อมใช้งาน

SELECT dept, COUNT(*) FROM University.Student
WHERE RollNo = 1 GROUP BY dept;

หากจำกัดไว้เพียงพาร์ติชันเดียวดังที่กล่าวมาข้างต้น การรวมข้อมูลจะมีประสิทธิภาพ แต่เมื่อดำเนินการกับทั้งตาราง จะกลายเป็นการสแกนทั่วทั้งคลัสเตอร์ ซึ่งเป็นเหตุผลว่าทำไม Cassandra ยังคงไม่เหมาะสมสำหรับการวิเคราะห์แบบเฉพาะกิจ และนั่นเป็นเหตุผลว่าทำไมการรายงานเชิงลึกจึงมักถูกผลักดันไปที่ Spark หรือคลังสินค้าภายนอก

Cassandra ในกรณีที่ข้อ

In Cassandraการดึงข้อมูลถือเป็นประเด็นละเอียดอ่อน คอลัมน์ถูกกรองเข้าไป Cassandra โดยการสร้างดัชนีบนคอลัมน์ที่ไม่ใช่คีย์หลัก

วากยสัมพันธ์

SELECT ColumnNames FROM KeyspaceName.TableName
WHERE ColumnName1 = Column1Value
  AND ColumnName2 = Column2Value;

ตัวอย่าง

  • นี่คือสแน็ปช็อตที่แสดงการดึงข้อมูลจากตารางนักเรียนโดยไม่มีการกรองข้อมูล

Cassandra ในกรณีที่ข้อ

SELECT * FROM University.Student;

ดึงข้อมูลสองระเบียนจากตารางนักเรียน

  • นี่คือภาพรวมที่แสดงการดึงข้อมูลจากนักเรียนพร้อมการกรองข้อมูล มีการเรียกข้อมูลหนึ่งระเบียน

ข้อมูลจะถูกกรองตามคอลัมน์ชื่อ โดยจะดึงข้อมูลทั้งหมดที่มีชื่อเท่ากับค่าที่กำหนดไว้ Guru99.

Cassandra ในกรณีที่ข้อ

SELECT * FROM University.Student WHERE name = 'Guru99';

กฎที่ควบคุมว่าคอลัมน์ใดบ้างที่เงื่อนไข WHERE สามารถอ้างอิงได้นั้น เป็นไปตามคีย์หลักโดยตรง

  • การขอ คีย์พาร์ติชั่น ต้องระบุข้อมูลให้ครบถ้วนเพื่อการสืบค้นที่มีประสิทธิภาพ เนื่องจากข้อมูลดังกล่าวใช้ระบุโหนดที่เก็บข้อมูล
  • Clusterคอลัมน์ อาจมีการจำกัดเพิ่มเติมได้ แต่จะจำกัดตามลำดับที่ประกาศไว้เท่านั้น ข้ามไปping หนึ่งในนั้นถูกปฏิเสธ
  • อนุญาตให้เปรียบเทียบช่วงค่าได้เฉพาะในคอลัมน์การจัดกลุ่มสุดท้ายที่อ้างอิงเท่านั้น ไม่ใช่คอลัมน์ก่อนหน้านั้น
  • ใด คอลัมน์อื่น จำเป็นต้องมีดัชนีรอง ซึ่งครอบคลุมอยู่ในส่วนต่างๆ ของเนื้อหา สร้างและลบดัชนี เกี่ยวกับการสอน

เมื่อคำขอถูกปฏิเสธ Cassandra มักแนะนำให้เพิ่ม ALLOW FILTERING เข้าไป ให้ถือว่านี่เป็นคำเตือนมากกว่าวิธีแก้ไข เพราะมันจะสแกนทุกพาร์ติชันในทุกโหนด และการเปลี่ยนแปลงสคีมามักจะเป็นวิธีแก้ปัญหาที่ถูกต้องเสมอ

คำถามที่พบบ่อย

การจัดกลุ่มคำสั่งแบบแบตช์จะช่วยให้คำสั่งเหล่านั้นสำเร็จหรือล้มเหลวพร้อมกัน ควรใช้เพื่อรักษาความสอดคล้องของตารางที่ซ้ำกัน ไม่ใช่สำหรับการโหลดข้อมูลจำนวนมาก เพราะการจัดกลุ่มคำสั่งในหลายพาร์ติชันจะทำให้ตัวประสานงานทำงานช้าลงอย่างมาก

หน้าเพจของไดรเวอร์จะแสดงขึ้นโดยอัตโนมัติโดยใช้โทเค็นสถานะการแบ่งหน้า ใน cqlsh คำสั่ง PAGING จะกำหนดขนาดหน้าเพจ หลีกเลี่ยงการจำลองคำสั่ง OFFSET ด้วยตัวนับ เพราะ Cassandra ไม่มีการข้ามแถวที่มีประสิทธิภาพping กลไก.

หากสำเนาข้อมูลหยุดทำงานนานกว่า gc_grace_seconds และข้อมูลในหลุมฝังศพถูกบีบอัดไปแล้ว สำเนาข้อมูลนั้นจะยังคงยึดแถวข้อมูลเก่าไว้และกระจายมันกลับไป การซ่อมแซมตามปกติจะช่วยป้องกันปัญหานี้ได้

การเลือกข้อมูลจากตารางเดียวแบบง่ายๆ นั้นแปลงได้ดี แต่ข้อมูลที่มีการเชื่อมต่อ (join), OR หรือซับควอรี (subquery) นั้นไม่มีคำสั่งเทียบเท่าโดยตรงใน CQL และ AI มักจะแก้ปัญหาแบบผิวเผินด้วยคำสั่ง ALLOW FILTERING ซึ่งไม่ใช่ทางออกที่ถูกต้อง

ใช่ การวาง TRACโดยปกติแล้ว คำสั่ง ING ON จะแสดงผลลัพธ์ที่ชัดเจนเกี่ยวกับการสแกนสุสาน การแบ่งพาร์ติชันขนาดใหญ่ หรือการกระโดดข้ามโหนด ตรวจสอบการเปลี่ยนแปลงสคีมาที่แนะนำในสำเนา ก่อนที่จะนำไปใช้

สรุปโพสต์นี้ด้วย: