PRQL: Ngôn ngữ truy vấn quan hệ theo kiểu pipeline
(github.com/PRQL)- PRQL là một ngôn ngữ hiện đại để biến đổi dữ liệu, hướng tới ngôn ngữ thay thế SQL dễ đọc, tường minh và khai báo như SQL
- Truy vấn được cấu thành như một pipeline logic trong đó mỗi bước biến đổi kế thừa kết quả từ bước trước, đồng thời hỗ trợ các lớp trừu tượng như biến và hàm
- PRQL được biên dịch sang SQL để có thể dùng cùng mọi cơ sở dữ liệu sử dụng SQL
- Ví dụ ngôn ngữ sử dụng các phép biến đổi như
from,filter,derive,group,aggregate,sort,take, vàfilterthay thế vai trò củaWHEREvàHAVINGtrong SQL - Các tính năng cú pháp gồm cách biểu diễn ngày tháng rõ ràng, coalesce, biến tham chiếu đến biến khác, F-string tương tự Python, S-string dùng SQL làm escape hatch, ký hiệu sắp xếp giảm dần và biểu thức phạm vi
- Cung cấp PRQL Playground để thử nghiệm trên trình duyệt, PRQL Book là tài liệu ngôn ngữ, và prql-lang.org với phần so sánh SQL và ví dụ
- Tính đến tháng 6/2026, có thể sử dụng thông qua các tích hợp được hỗ trợ hoặc language binding được hỗ trợ, nhưng vẫn còn một số lỗi và tính năng còn thiếu, và phạm vi sẵn sàng để triển khai cho các nhóm phi kỹ thuật hiện vẫn bị giới hạn ở những truy vấn khá đơn giản
- Trọng tâm phát triển là công việc resolver mới, xử lý các lỗi ưu tiên cao, thu hẹp khoảng cách tính năng còn lại để có thể dùng cho phần lớn truy vấn SQL tiêu chuẩn, và bổ sung hỗ trợ thử nghiệm cho module cùng các dự án nhiều tệp
- Các điểm tích hợp gồm VS Code extension, Jupyter integration, QStudio integration, Jupyter magic, pyprql Docs, prqlc-js
- Kho lưu trữ gồm trình biên dịch
prqlcđược viết bằng Rust và khu vực nội dung webweb;prqlcbiên dịch PRQL sang SQL và bao gồm CLI cùng nhiều language binding
1 bình luận
Các ý kiến trên Hacker News
Các ví dụ trên website https://prql-lang.org/ có vẻ là ưu điểm lớn nhất của PRQL, đặc biệt SQL được sinh ra rất gọn gàng và trực quan, trông như dạng mà mình có thể tự viết
10–15 năm trước, người ta tạo ra các cơ sở dữ liệu mới như Mongo, Riak, Influx rồi thuyết phục nhà phát triển ứng dụng dùng cho dự án mới; còn hiện nay có nhiều lựa chọn bảo thủ hơn như EdgeDB, TimescaleDB, PRQL, tức là đặt add-on hoặc bộ tiền xử lý truy vấn lên Postgres, nên dễ đưa vào sử dụng hơn nhiều
Schema và migration của Edge cũng tốt, nhưng cú pháp PRQL trực quan hơn. Trong mã ứng dụng đã có rất nhiều pipeline biến đổi dữ liệu như chuỗi map/filter của TypeScript, iterator của Rust, enumerable của Ruby, stream của Java, .NET LINQ, Rx trong nhiều ngôn ngữ, nên khái niệm này rất quen thuộc. Điểm tuyệt vời là có thể lấy SQL tốt từ PRQL để lưu lại, kiểm tra về sau, xem kế hoạch thực thi và thêm chỉ mục ở những nơi cần thiết
Ví dụ cố tình làm SQL trông dài dòng hơn.
from employees / select {id, first_name, age} / sort age / take 10có vẻ tốt hơnSELECT ... FROM ... ORDER BY ... LIMIT ...được tách thành nhiều dòng, nhưng SQL thực tế cũng có thể viết làselect id, first_name, age from employees order by age limit 10; thay vì không có ngoặc nhọn thì chỉ khác khoảng giữaorder byvàsort, gần như chỉ là chênh lệch một hai ký tựViệc có thể thay đổi thứ tự các phần của truy vấn đúng là điều ai cũng phàn nàn về SQL, nhưng đổi lại lại có nhiều loại ngoặc, dấu hai chấm và cú pháp khác được đưa vào không rõ lý do, mà dường như cũng chẳng làm được điều gì SQL vốn chưa làm được. Tôi tò mò điểm hấp dẫn của nó là gì
Gần đây đã merge hỗ trợ PRQL vào ClickHouse: https://github.com/ClickHouse/ClickHouse/pull/50686
Hiện vẫn giống thử nghiệm hơn, chưa chắc có thực sự dùng được hay hữu ích không. Cũng có một chút lo ngại liên quan đến Rust: https://github.com/ClickHouse/ClickHouse/issues/52053#issuecomment-1643805521
Mong PRQL phát triển mạnh và trở thành ngôn ngữ được hỗ trợ hạng nhất của Postgres. Đại số quan hệ rất đẹp, nhưng SQL là một thiết kế đầu tiên lộn xộn đáng lẽ phải bị thay thế từ nhiều thập kỷ trước
Ngay cả Codd cũng không hài lòng với SQL. Thứ ông phát minh ra thật đáng kinh ngạc, nhưng kể từ đó chúng ta đã học được rất nhiều về thiết kế ngôn ngữ lập trình
ORDER BYVấn đề này lộ ra theo kiểu khi bọc bằng truy vấn con thì thứ tự của quan hệ biến mất, khá ngoài dự đoán. Mô hình dữ liệu của PRQL rất giống mô hình quan hệ, khác biệt lớn là quan hệ được định nghĩa là mảng tuple, nên có thứ tự. Hy vọng PRQL sẽ được biết đến như “ngôn ngữ quan hệ Mk II”
Cũng có plugin DBeaver [3], dù cần tài liệu hóa và đơn giản hóa khả năng sử dụng hơn nữa, nhưng có khả năng với nó cũng truy vấn được Postgres bằng PRQL. Cuối cùng, dùng pyprql [4] thì có thể truy vấn Postgres trong Jupyter notebook
[1]: https://github.com/ywelsch/duckdb-prql
[2]: https://duckdb.org/docs/extensions/postgres_scanner.html
[3]: https://github.com/PRQL/prql/issues/1643
[4]: https://github.com/PRQL/pyprql
Nhân tiện, tôi là người đóng góp cho PRQL
Khi ấy tôi nghĩ có lẽ do mình chưa biết đủ để hiểu vì sao nó phải như vậy, nhưng giờ tôi biết là chẳng có lý do nào cả. SQL đã trở nên giống ngôn ngữ tự nhiên, nên dù vô lý cũng không thể phản bác mà cứ phải nói như vậy. Nhưng SQL không phải ngôn ngữ tự nhiên, và ta có thể làm tốt hơn
Nếu phàn nàn chính về SQL là không thể đổi thứ tự
SELECT,FROM,WHERE, thì với một ngôn ngữ được thiết kế từ thập niên 70, nó vẫn khá ổnNgược lại, PRQL trông có vẻ có nhiều nhiễu tùy ý trong cú pháp. Không rõ vì sao tôi nên thích
join side:left p=positions (p.id==employees.employee_id)hơnLEFT JOIN positions AS p ON p.id = employees.employee_idCách như PRQL, từ trên xuống dưới, mỗi bước là một phép biến đổi của bước trước, hợp lý hơn nhiều. SQL cần sổ tay tham chiếu, còn PRQL có cảm giác như viết ra đúng những gì bạn muốn truy vấn làm. Tuy vậy cú pháp join của PRQL rất tệ; lẽ ra nên giữ các từ khóa kiểu
left jointường minh, và cũng có thể thiết kế tốt hơn phần bí danh cùng cách viết tắt cột joinThứ nhất, trong cùng một
selectkhông thể dùng một cột đã chọn trước đó ở phần sau. Không thể viết kiểugnarly_calculation AS some_valuerồisome_value * 2 AS some_value_doubled, mà phải bọc bằng truy vấn con. Thứ hai, không thể chỉ định toàn bộ các cột trừ một số cột nhất định. Khi cần kéo các phép tính trung gian lên từ truy vấn con nhưng không cần trong đầu ra cuối cùng, bạn không thể nói kiểu* EXCEPT some_value, mà phải liệt kê tất cả các cột đầu ra mong muốnVí dụ được chọn có thể là trường hợp dấu ngoặc và dấu phẩy giúp ích rất nhiều, nhưng trong bối cảnh toàn bộ ngôn ngữ thì không tệ đến vậy.
:được dùng nhất quán như đối số có tên, còn=có vẻ được dùng cho bí danhjoin, và từ đầu tiên của câu làjoin, nên thao tác thực sự là gì trở nên rõ ràng hơnNgay cả với ví dụ gọi hàm thông thường,
foo(bar)cũng tốt hơn “bar to foo()”PRQL 0.9 vừa mới được phát hành vài giờ trước, nên thời điểm khá đúng lúc. Ghi chú phát hành có thể xem ở đây: https://github.com/PRQL/prql/releases/tag/0.9.0
Có một thay đổi phá vỡ tương thích khá lớn: cú pháp tuple đổi từ
[]sang{}. Ban đầu chúng trông giống list, nhưng theo thời gian chúng tôi nhận ra thực ra chúng là tuple. Như ghi chú phát hành nói, việc để trống[]sẽ cho phép sớm bắt đầu hỗ trợ mảng. Nhân tiện, tôi là người đóng góp cho PRQLGiới hạn của PRQL là theo thiết kế nó chỉ hỗ trợ SELECT. Muốn chèn/sửa/xóa dữ liệu thì phải quay lại SQL
Nhà khoa học dữ liệu trong nhóm có thể đưa truy vấn bằng PRQL, nhưng để đưa vào pipeline dữ liệu thực tế thì phải dịch sang SQL. Sẽ tốt nếu ít nhất hỗ trợ một số chức năng hạn chế, chẳng hạn chèn vào một bảng tạm mới. Ví dụ dạng như
from tracks / filter artist == "Bob Marley" / save bob_marley_tmpinsert/update/deletephải nằm ở cuối pipeline và nhận tên bảng làm đối sốSQL kiểu
UPDATE counters SET value = value + 1 WHERE name LIKE 'prefix.%'có thể được viết trong PRQL nhưfrom counters / filter startswith(name, 'prefix.') / derive { new_value = value + 1 } / select { name, new_value } / update countersBài viết không thể thiếu ở đây: “I don't want to learn your garbage query language” [1]
[1] https://erikbern.com/2018/08/30/i-dont-want-to-learn-your-garbage-query-language.html
Mục tiêu của PRQL là trở thành một ngôn ngữ tuyệt vời để tích hợp và xây dựng lên trên. Chúng tôi không muốn tạo N ngôn ngữ cho N cơ sở dữ liệu. PRQL sẽ luôn là mã nguồn mở và sẽ không tạo sản phẩm thương mại, nên tôi nghĩ nó khả thi hơn nhiều so với các ngôn ngữ riêng theo từng cơ sở dữ liệu/từng sản phẩm. Tôi là nhà phát triển PRQL
Show HN trước đó: https://news.ycombinator.com/item?id=31897430
“Show HN: PRQL 0.2 – a better SQL” được maximilianroos đăng ngày 27/06/2022, đạt 378 điểm và có 161 bình luận
Bài gốc đề xuất ban đầu: https://news.ycombinator.com/item?id=30060784
“PRQL – A proposal for a better SQL” được maximilianroos đăng ngày 24/01/2022, đạt 650 điểm và có 295 bình luận
Gợi nhớ đến KQL của Microsoft: https://learn.microsoft.com/en-us/azure/data-explorer/kusto/query/
Cú pháp không quá quan trọng; điều quan trọng là bộ tối ưu hóa làm gì
Hiện nay, nhiều vấn đề của SQL trông như gánh nặng từ quá khứ. Vì các engine cũ không xử lý tốt cú pháp hiện đại, nhiều người đã được rèn để viết những truy vấn khó đọc, phức tạp và lồng nhau sâu. Chẳng hạn, với biểu thức bảng chung (CTE), engine thường vật lý hóa ngay lập tức, nên kiểu viết cũ như
SELECT FROM (SELECT FROM (SELECT FROM A JOIN (SELECT ) B ON A.x=B.x)))từng xuất hiện tràn lanNhờ việc cải thiện cách engine xử lý CTE, ngày càng dễ viết các truy vấn dễ hiểu và có thể kết hợp như
WITH A AS (...), WITH B AS (...), WITH C AS (SELECT y FROM A) SELECT result FROM C WHERE .... Khi có thêm các tính năng như hàm cửa sổ hiện đại,SELECT * EXCEPT, hay những khả năng phức tạp hơn nhưTOP X FOLLOWING, SQL có thể trở nên đơn giản hơnTrong bối cảnh như vậy, tôi không nghĩ những cải tiến nhỏ về hình thức cú pháp khác như PRQL mang lại lợi ích lớn. Có thể viết lại thành pipeline trông giống mệnh lệnh, nhưng bộ tối ưu hóa cũng có thể loại bỏ một phần trong đó. Đúng là có những điều SQL cần làm tốt hơn, nhưng tôi vẫn chưa thấy lập luận thuyết phục nào cho các khác biệt mang tính bề ngoài hoặc cú pháp