Các tính năng mới của query planner trong Postgres 16
(citusdata.com)- PostgreSQL 16 bổ sung 10 cải tiến cho query planner/optimizer, mở rộng lựa chọn kế hoạch thực thi cho
DISTINCT, tổng hợp, join, window function và truy vấn trên bảng phân vùng - Trong
SELECT DISTINCT, tổng hợp cóORDER BY/DISTINCT, và xử lý sauMerge Join, PostgreSQL 16 tận dụng đầu vào đã được sắp xếp một phần tích cực hơn để tạo kết quả với ít bộ nhớ hơn so với sắp xếp toàn bộ - Hỗ trợ Memoize bên trong
UNION ALL,Right Anti Join, và parallel hash join choFULL/RIGHTjoin tập trung vào việc giảm chi phí tra cứu lặp lại và tạo các bảng băm lớn - Window function giảm xử lý
RANGEkhông cần thiết và giảm cácWindowAggphải chạy đến hết; một số hàm có thể dừng sớm tùy theo điều kiện - Tất cả cải tiến đều được bật mặc định, vì vậy trước và sau khi nâng cấp lên PostgreSQL 16, rất đáng để so sánh
EXPLAINvà thời gian thực thi trên workload thực tế
Phạm vi cải tiến planner của PostgreSQL 16
- PostgreSQL 16 đưa vào nhiều cải tiến cho query planner, giúp nhiều truy vấn SQL có thể chạy nhanh hơn so với các phiên bản PostgreSQL trước đó
- Bài viết giải thích chi tiết hơn các cải tiến planner có trong ghi chú phát hành PG16, đồng thời đề cập đến so sánh đầu ra
EXPLAINgiữa PG15 và PG16 cùng các ví dụ kiểm thử có thể tái hiện - Ở đây, planner là thành phần thường được gọi là optimizer trong các cơ sở dữ liệu quan hệ khác
Tối ưu hóa sắp xếp và DISTINCT
-
Dùng Incremental Sort trong
SELECT DISTINCT- Incremental Sort lần đầu được thêm vào PostgreSQL 13; khi kết quả đã được sắp xếp theo các cột đứng trước, nó chỉ sắp xếp các cột còn lại để giảm chi phí
- Planner của PostgreSQL 16 cũng cân nhắc Incremental Sort cho các truy vấn
SELECT DISTINCT - Ví dụ, nếu có chỉ mục btree trên cột
avà cần thứ tựa, b, có thể dùng chỉ mục để lấy kết quả đã sắp xếp theoa, rồi chỉ sắp xếpbmỗi khi giá trịathay đổi - Với quicksort của PostgreSQL, sắp xếp nhiều nhóm nhỏ có thể hiệu quả hơn sắp xếp một nhóm lớn
- Trong truy vấn ví dụ, PG15 dùng
HashAggregatevà quét tuần tự, còn PG16 chọn chỉ mụcdistinct_test_a_idxvàIncremental Sort Presorted Key: atrong đầu ra PG16 có nghĩa là đầu vào đã được sắp xếp theoađã được tận dụng- Cách dùng hash của PG15 spill khoảng 30MB ra đĩa, trong khi bộ nhớ tối đa của
Incremental Sortở PG16 là 26KB - Thời gian thực thi giảm từ 414.226ms trên PG15 xuống 263.167ms trên PG16
-
Tối ưu hóa tổng hợp có
ORDER BYhoặcDISTINCT- Trong PostgreSQL 15 trở xuống, các hàm tổng hợp có mệnh đề
ORDER BYhoặcDISTINCTluôn thực hiện sắp xếp bên trong nodeAggregate - Planner của PostgreSQL 16 có thể tạo kế hoạch thực thi cung cấp các hàng theo đúng thứ tự cho node
Aggregate, và executor sẽ bỏ qua sắp xếp nội bộ nếu đầu vào đã được sắp xếp - Trong ví dụ
COUNT(DISTINCT b), cả PG15 và PG16 đều dùngGroupAggregatevàIndex Only Scan, nhưng đầu ra PG15 xuất hiệntemp read=4540 written=4560 - I/O file tạm này là kết quả của việc sắp xếp ngầm định trong PG15 bị spill ra đĩa
- Đầu ra PG16 không có I/O tạm tương ứng, và thời gian thực thi tăng tốc hơn 2 lần, từ 302.693ms trên PG15 xuống 115.534ms trên PG16
- Trong PostgreSQL 15 trở xuống, các hàm tổng hợp có mệnh đề
Cải tiến tra cứu lặp lại và kế hoạch join
-
Áp dụng Memoize bên trong
UNION ALL- Plan node
Memoizelần đầu được giới thiệu trong PostgreSQL 14, hoạt động như một lớp cache giữaNested Loopđược tham số hóa và đầu vào bên trong - Planner của PostgreSQL 16 cũng cân nhắc dùng
Memoizekhi bên trongNested Loopđược tham số hóa có truy vấnUNION ALL - Trong ví dụ, PG15 thực thi
Append1 triệu lần, nhưng PG16 đặtMemoizephía trênAppend Memoizecủa PG16 ghi nhậnHits: 999990,Misses: 10,Memory Usage: 2kB- Số lần thực thi
Appendgiảm từ 1 triệu lần trên PG15 xuống còn 10 lần trên PG16 - Thời gian thực thi nhanh hơn khoảng 6 lần, từ 1926.151ms trên PG15 xuống 282.120ms trên PG16
- Plan node
-
Hỗ trợ Right Anti Join
- Trong
Hash JoincủaINNER JOIN, thường có lợi hơn khi tạo bảng băm trên bảng nhỏ hơn - Bảng băm nhỏ cần ít công tạo hơn, thân thiện hơn với cache CPU, và cũng giảm khả năng CPU stall khi phải chờ dữ liệu từ bộ nhớ chính
- Trước PostgreSQL 16,
Anti Joinluôn đặt bảng được nhắc tới trongNOT EXISTSở phía trong của join, nên có thể phải tạo bảng băm trên bảng lớn hơn - PostgreSQL 16 hỗ trợ Right Anti Join, cho phép băm phía nhỏ hơn trong hai bảng
- Trong ví dụ, PG15 băm bảng
largecó 1 triệu hàng và dùng 6446KB bộ nhớ, còn PG16 băm bảngsmallcó 100 hàng và chỉ dùng 12KB - Thời gian thực thi gần như giảm một nửa, từ 139.023ms trên PG15 xuống 77.076ms trên PG16
- Trong
-
Parallel hash join cho FULL/RIGHT join
- PostgreSQL 11 giới thiệu
Parallel Hash Join, trong đó nhiều worker song song cùng tham gia tạo một bảng băm duy nhất Parallel Hash Joincủa PostgreSQL 16 hỗ trợ các loại joinFULLvàRIGHT- Các kế hoạch
FULL OUTER JOINvàRight Joincũng có thể chạy song song - Trong ví dụ
FULL JOIN, PG15 dùng mộtHash Full Joinđơn lẻ, còn PG16 dùngParallel Hash Full JoinvàGather - Đầu ra PG16 hiển thị
Workers Planned: 1,Workers Launched: 1 - Thời gian thực thi giảm đáng kể, từ 220.677ms trên PG15 xuống 129.769ms trên PG16
- PostgreSQL 11 giới thiệu
Tối ưu hóa window function
-
Bỏ qua xử lý RANGE không cần thiết
- Với các window function như
row_number(),rank(),dense_rank(),percent_rank(),cume_dist(),ntile(), nếu window clause không có tùy chọnROWS, PostgreSQL dùng tùy chọnRANGEmặc định - Tùy chọn
RANGEphải kiểm tra các hàng phía trước để tìm peer row có cùng giá trị sắp xếp, và chi phí có thể tăng nếu có nhiều giá trị giống nhau theoORDER BY - Các hàm trên không thay đổi hành vi tùy theo việc chỉ định
ROWShayRANGE, nhưng executor trước PostgreSQL 16 không phân biệt được điều này nên phải kiểm tra peer row trong mọi trường hợp - Planner của PostgreSQL 16 biết window function nào bị ảnh hưởng bởi tùy chọn
ROWS/RANGE, và truyền thông tin để executor bỏ qua xử lý không cần thiết - Trong ví dụ
row_number() <= 10, PG15 đọc 50.410 hàng từ chỉ mục rồi mới dừng, còn PG16 chỉ đọc 11 hàng - PG16 tận dụng việc khi
row_numberđạt 11 thì sẽ không còn hàng nào thỏa điều kiện<= 10 - Thời gian thực thi nhanh hơn hơn 500 lần, từ 29.775ms trên PG15 xuống 0.058ms trên PG16
- Với các window function như
-
Mở rộng dừng sớm cho window function tăng đơn điệu
- PostgreSQL 15 đã cho phép dừng thực thi
WindowAggsớm khi điều kiện trong mệnh đềWHEREtrở thành false một lần và không thể trở lại true đối với một số window function nhất định - PostgreSQL 16 mở rộng đối tượng áp dụng tối ưu hóa này sang
ntile(),cume_dist(),percent_rank() - Trong PostgreSQL 15, tối ưu hóa này chỉ áp dụng cho
row_number(),rank(),dense_rank(),count(),count(*) - Trong ví dụ
percent_rank() <= 0.01, PG15 xử lý điều kiện bằngFiltercủa subquery, vàWindowAggxử lý toàn bộ 50.000 hàng - PG16 dùng cùng điều kiện đó làm
Run Condition, qua đó dừng thực thiWindowAggsớm - Thời gian thực thi nhanh hơn hơn 4 lần, từ 84.358ms trên PG15 xuống 19.454ms trên PG16
- PostgreSQL 15 đã cho phép dừng thực thi
Bảng phân vùng và xử lý DISTINCT hiển nhiên
-
Loại bỏ LEFT JOIN trên bảng phân vùng
- Từ lâu PostgreSQL đã có thể loại bỏ
LEFT JOINkhông cần thiết cho truy vấn và không có khả năng gây trùng lặp hàng - Trước PostgreSQL 16, loại bỏ LEFT JOIN đối với bảng phân vùng chưa được hỗ trợ
- Lý do là chưa có chứng minh cần thiết để xác định các hàng bên trong không có khả năng nhân đôi các hàng bên ngoài trong bảng phân vùng
- Planner của PostgreSQL 16 cũng áp dụng tối ưu hóa loại bỏ
LEFT JOINcho bảng phân vùng - Tối ưu hóa này có thể đặc biệt hữu ích với view
- Vì ngay cả khi view có nhiều cột, truy vấn thực tế không phải lúc nào cũng đọc tất cả các cột
- Trong ví dụ, kế hoạch PG15 bao gồm join với
part_tab, còn kế hoạch PG16 chỉ thực hiện quét tuần tựnormal_table
- Từ lâu PostgreSQL đã có thể loại bỏ
-
Xử lý DISTINCT có kết quả chắc chắn là một giá trị bằng Limit
- Nếu planner của PostgreSQL có thể phát hiện rằng tất cả hàng đều có cùng giá trị, nó có thể bỏ qua plan node dùng để loại bỏ trùng lặp kết quả
- PostgreSQL 16 tận dụng việc kết quả chỉ chứa cùng một giá trị khi tất cả các cột đích của
DISTINCTđều bị cố định bằng điều kiện bằng trong mệnh đềWHERE, và xử lý bằngLIMIT 1 - Trong truy vấn ví dụ
SELECT DISTINCT a,b,c FROM abc WHERE a = 5 AND b = 5 AND c = 5, mỗi cộtDISTINCTđều bị giới hạn về cùng một giá trị - PG15 đọc toàn bộ kết quả rồi dùng toán tử
Uniqueđể rút xuống 1 hàng - PG16 dùng
Limitvà quét tuần tự để chỉ trả về 1 hàng - Thời gian thực thi nhanh hơn hơn 1200 lần, từ 30.381ms trên PG15 xuống 0.025ms trên PG16
Mở rộng tận dụng Incremental Sort sau Merge Join
- Trước PostgreSQL 16, khi cân nhắc
Merge Join, planner chỉ dùng thứ tự sắp xếp của join nếu thứ tự đó khớp chính xác với yêu cầu của tác vụ cấp trên nhưDISTINCT,GROUP BY,ORDER BY - Quy tắc này chưa phản ánh đầy đủ việc
Incremental Sortcó thể tận dụng đầu vào đã được sắp xếp một phần trong tác vụ cấp trên - PostgreSQL 16 nới lỏng quy tắc xét thứ tự
Merge Jointừ “phải khớp chính xác” thành “ít nhất 1 cột đứng trước phải được sắp xếp đúng” - Thay đổi này giúp planner có thể dùng Incremental Sort thường xuyên hơn để điều chỉnh kết quả
Merge Joincho phù hợp với tác vụ cấp trên- Incremental Sort tận dụng đầu vào đã sắp xếp một phần để sắp xếp theo từng batch nhỏ, nhờ đó có thể giảm lượng bộ nhớ dùng và số lần so sánh so với sắp xếp toàn bộ
- Trong ví dụ, PG15 dùng
Sorttoàn bộ sauMerge Join, còn PG16 dùngIncremental Sort- Bộ nhớ tối đa của
Incremental Sorttrên PG16 là 26KB - Thời gian thực thi giảm nhẹ từ 1010.738ms trên PG15 xuống 915.589ms trên PG16, còn bộ nhớ dùng cho sắp xếp thì giảm đáng kể
- Bộ nhớ tối đa của
Cách áp dụng và kiểm chứng thực tế
- Cả 10 cải tiến planner của PostgreSQL 16 đều được bật mặc định
- Mỗi tối ưu hóa được áp dụng trong mọi trường hợp có thể, hoặc được áp dụng có chọn lọc khi planner nhận định là hữu ích
- Nếu đang dùng phiên bản PostgreSQL cũ, bạn có thể chạy workload thực tế trên PostgreSQL 16 để xác định những truy vấn nào nhanh hơn
- Phản hồi từ sử dụng thực tế có thể được chia sẻ qua mailing list pgsql-general@postgresql.org
1 bình luận
Ý kiến trên Hacker News
Sẽ thật tuyệt nếu query planner của PostgreSQL có thể lập kế hoạch lại truy vấn khi đang thực thi giữa chừng
Các truy vấn chậm một cách bệnh lý thường xảy ra vì planner không biết những thông tin cần thiết về phân bố dữ liệu nên ước tính chi phí sai; chuyện thời gian chạy thành 1 giây thay vì 1ms, tức chênh lệch 1000 lần, cũng rất dễ xảy ra
Thống kê bảng không thể chính xác 100%, nên sau khi bắt đầu truy vấn, nếu tiến độ chậm hơn dự kiến, sẽ tốt nếu đưa lại các thông tin tiến độ hiện tại như số trang đã quét và số tuple khớp vào planner để tạo kế hoạch mới
Tuy nhiên PostgreSQL không tạo xong toàn bộ kết quả rồi mới gửi, mà gửi theo kiểu streaming, nên để đổi kế hoạch giữa chừng sẽ phải theo dõi các kết quả đã gửi cho client, kéo theo thay đổi hạ tầng lớn
Hơn nữa client còn có thể đảo hướng giữa truy vấn để yêu cầu lại các kết quả trước đó theo thứ tự ngược, khiến độ phức tạp tăng thêm
Vì thậm chí không có gì đảm bảo kế hoạch mới sẽ trả về cùng các tuple. Ví dụ, nếu không có
ORDER BYnhưSELECT * FROM table LIMIT 10, tuple nào được trả về là không xác địnhCó lẽ cách dễ hơn là xếp X tuple vào một hàng đợi, rồi khi hàng đợi đầy thì bắt đầu gửi. Sau khi hàng đợi đã đầy thì coi như đã quá muộn để lập kế hoạch lại và cố định ở kế hoạch hiện tại
Người dùng có thể điều chỉnh X để chấp nhận dùng nhiều bộ nhớ hơn và tăng độ trễ đến tuple đầu tiên, đổi lại có thêm thời gian để đổi kế hoạch
Truy vấn mới không thể chỉ đơn giản bỏ qua N kết quả đầu, mà phải đối chiếu từng hàng đã gửi với một danh sách
Tôi dùng công cụ này để trực quan hóa truy vấn: https://explain.dalibo.com/
Cũng có https://www.pgexplain.dev/; trước đây output kém hơn, nhưng giờ cả hai trông có vẻ tương tự nhau
Tôi cũng tò mò liệu có công cụ làm sạch execution plan nào hữu ích trong tình huống này không
Cải thiện query planner luôn được hoan nghênh, và đó là một phần rất quan trọng trong cơ sở dữ liệu. Tất nhiên thường thì nó nổi bật nhất khi không làm đúng như tôi muốn
Cá nhân tôi khá bực với JIT trong các phiên bản PostgreSQL gần đây. Heuristic quyết định khi nào dùng nó trông hoàn toàn không vững
Tôi đã thấy điều này trong các truy vấn điển hình do ORM tạo ra: bản thân truy vấn thì đơn giản nhưng kéo vào nhiều bảng bằng join. Không có JIT thì xong trong vài mili giây, nhưng JIT thêm 1–1,5 giây, khiến nó cực chậm ngay cả với dữ liệu nhỏ
Giờ thì tôi biết chỉ cần tắt JIT là được, nhưng với người dùng chưa tìm ra vì sao chậm, điều này có thể phá hỏng ấn tượng về PostgreSQL rất nhiều. Tôi thích PostgreSQL, nhưng bật JIT theo mặc định có vẻ quá rủi ro
Trong PG16, nó chỉ nhìn vào tổng chi phí ước tính của kế hoạch, chứ không xét số biểu thức cần biên dịch
Biên dịch vài biểu thức thì nhanh, nhưng nếu truy vấn một bảng phân vùng có hàng trăm partition và tất cả partition đó đều nằm trong kế hoạch, trình biên dịch JIT sẽ có rất nhiều việc phải làm
Tôi cùng một đồng nghiệp có đoạn mã để cải thiện việc này, nhưng ở thời điểm hiện tại chưa chắc nó có vào PG17 hay không
Tôi đã tìm các thảo luận liên quan đến JIT trên mailing list PostgreSQL nhưng không thấy lý do nào thuyết phục
Với workload OLTP thì tắt JIT là đúng
Tôi không dùng ORM, nên đây cũng không đơn giản chỉ là do các mẫu truy vấn kỳ lạ
Ngược lại, song song hóa truy vấn có thể thực sự hữu ích, và quan trọng hơn là hiếm khi gây hại
Sau khi cập nhật vài package bằng
apt, một truy vấn lớn chạy mỗi 5 phút đột nhiên bắt đầu thất bại. Chính xác là PostgreSQL âm thầm ngắt kết nối giữa lúc thực thi truy vấn mà không để lại logTôi kiểm tra bằng cách chạy
EXPLAINthủ công và thấy chỉ biến thể truy vấn dùng JIT mới hỏng, còn biến thể không dùng thì ổn. Tắt JIT xong mọi thứ lại bình thườngTôi tò mò không biết những thay đổi này thực sự phát huy tác dụng thường xuyên đến mức nào trong các truy vấn thực tế. Đặc biệt, thay đổi “dùng
Limitthay vìUniqueđể triển khaiDISTINCTkhi có thể” có cảm giác chỉ áp dụng cho những truy vấn cực kỳ ngớ ngẩnTôi cũng tò mò liệu các nhà phát triển PostgreSQL có nguồn thông tin nào để đánh giá điều này không
Nếu cải tiến DISTINCT giúp hệ thống vững hơn trước các truy vấn kém thì lợi ích thu được là lớn. Nó sẽ không sửa được mọi vấn đề, nhưng bất kỳ cải tiến nào cũng đáng hoan nghênh
pgsql-hackersTôi đồng ý rằng khả năng được áp dụng thường xuyên là thấp, nhưng điểm hay là việc phát hiện xem có thể áp dụng hay không đơn giản như kiểm tra một con trỏ có phải
NULLhay khôngViệc phát hiện rất đơn giản và phần lớn trường hợp sẽ không áp dụng được, nhưng trong những trường hợp có thể áp dụng thì nó có thể đem lại cải thiện hiệu năng đáng kể
Có lẽ đây không phải vấn đề cực kỳ phổ biến, nhưng nếu thỉnh thoảng xuất hiện thì tôi cũng không ngạc nhiên
select distinct email from users where email = ?Tôi nghĩ số hàng có cùng email không vượt quá 100. Phần lớn là người dùng thử nghiệm lẽ ra có thể xóa, nhưng chuyện hơi lạc đề rồi
Tôi ước PostgreSQL có chế độ nghiêm ngặt để kiểm thử ứng dụng. Đó sẽ là một chế độ chỉ nhìn vào bản thân truy vấn, độc lập với thống kê, trong đó nếu có một chỉ mục giúp truy vấn cải thiện về mặt tiệm cận nhưng chỉ mục đó lại không tồn tại thì trả về lỗi
Cũng sẽ tốt nếu có lệnh
CREATE INDICES FORđể tạo các chỉ mục đó cho việc nâng cấp ứng dụng, và có cả chế độ tự động tạo chỉ mục cho mục đích tương tác/phát triểnNhìn chung, hệ thống nên được thiết kế để việc thực thi không tối ưu về mặt tiệm cận tuyệt đối không bao giờ xảy ra
Tôi không hiểu vì sao họ không triển khai hint
pg_hint_plan. Rủi ro của hint là dù đúng ở thời điểm viết, nó có thể trở nên tệ hơn khi kích thước bảng hoặc độ lệch dữ liệu thay đổiLần trước khi xem thảo luận về hint, tôi nhớ là không có phản đối chung nếu đó là cách không ràng buộc planner quá chặt và vẫn có thể thích ứng với các thay đổi dữ liệu cơ bản
Ví dụ, thay vì chỉ định rằng một predicate cụ thể khớp với 10 hàng, ta báo cho hệ thống biết rằng có tương quan giữa hai cột
https://news.ycombinator.com/item?id=2179433 (60 bình luận, năm 2011)
Lập trường chính thức trên wiki PostgreSQL nằm ở https://wiki.postgresql.org/wiki/OptimizerHintsDiscussion
Lập trường là “không quan tâm đến hint theo đúng cách thường được triển khai trong các cơ sở dữ liệu khác”
Các vấn đề của hệ thống hint hiện có được nêu gồm làm giảm khả năng bảo trì mã ứng dụng, cản trở nâng cấp, khuyến khích thói quen DBA xấu, và không phù hợp khi quy mô dữ liệu mở rộng
Tôi không muốn trách lập trường đó, nhưng thật bực bội khi PostgreSQL chọn một kế hoạch ngớ ngẩn mà ta lại không thể thuyết phục nó đưa ra lựa chọn hợp lý
Một người bạn làm Microsoft DBA cho các doanh nghiệp tầm trung nói rằng không thể làm việc nghiêm túc với PostgreSQL. Thậm chí anh ấy còn bảo đã sốc khi biết PostgreSQL không có query planner
Tạm gác chuyện chế giễu sang một bên, tôi tò mò liệu lập luận lớn hơn rằng MSSQL có thể xử lý quy mô mà PostgreSQL không phù hợp có hợp lý chút nào không. Trực giác thì thấy vô lý, nhưng tôi hoàn toàn không phải DBA
Họ đã giải quyết bằng cách đổ tiền và phần cứng, tức là thêm tiền, vào cho đến khi vấn đề được xử lý. Tất nhiên cũng có công nghệ thông minh trong đó, nhưng về cơ bản đã có nhiều kỹ sư hơn rất nhiều được投入 trong thời gian dài
Chúng có thể mở rộng theo chiều ngang lớn hơn mức PostgreSQL có thể làm một cách hợp lý
Tuy vậy PostgreSQL cũng đang bắt kịp, và MySQL/MariaDB có thể nói là từ trước đến nay vẫn khá ổn ở mảng này. Các lựa chọn mở rộng theo chiều ngang đang ngày càng tốt hơn
Giờ đây cũng dễ hơn để vận hành các cụm PostgreSQL nhiều terabyte trên số lượng máy ít, xử lý lưu lượng lớn, và đưa “big data” vào các cơ sở dữ liệu chuyên biệt hơn. Cách cũ là nhồi mọi thứ vào MSSQL/Oracle có thể đã hơi lỗi thời
Điều bạn của bạn nói có thể là việc PostgreSQL không có cách cache hoặc cố định query plan. PostgreSQL sẽ lập kế hoạch lại cho mỗi câu lệnh trừ khi dùng câu lệnh được chuẩn bị thủ công, và việc đó cũng chỉ hoạt động theo từng kết nối
MSSQL đã cache và tái sử dụng plan từ lâu, nên planner có thể dành nhiều thời gian hơn cho việc lập kế hoạch. Nó cũng có hint và có thể cố định plan
PostgreSQL thật sự cần hint. Dù optimizer rất tốt, đôi khi tôi biết rõ hơn và muốn buộc nó nghe theo mình
Ngoài ra PostgreSQL không có clustered index thật sự và mọi bảng đều là heap. Trong MSSQL, phần lớn mọi người dùng nó thường xuyên, thường đặt khóa chính làm clustered index để bản thân bảng trở thành index và không có tham chiếu gián tiếp khi tra cứu theo khóa
Thú vị là SQLite thì ngược lại: bảng luôn có clustered index, dù bạn có tạo hay không; còn MSSQL cho phép chọn giữa heap và bảng tổ chức theo index
Có những trường hợp cơ sở dữ liệu PostgreSQL rất lớn vẫn hoạt động tốt, nên PostgreSQL chắc chắn cũng có thể mở rộng
Tuy nhiên SQL Server cũng có các tính năng mà PostgreSQL không có, và nếu những tính năng đó quan trọng thì nó có thể phù hợp hơn cho một số use case nhất định. Rốt cuộc đây là các cơ sở dữ liệu khác nhau, với điểm mạnh và điểm yếu khác nhau
Ban đầu tôi định viết rằng nếu không phải vì các ứng dụng do vendor cung cấp yêu cầu SQL Server, tôi đã khuyến nghị công ty chuyển sang PostgreSQL
Nhưng rồi tôi nhận ra sẽ phải thay thế nhiều thứ đến mức nào trong những thứ Microsoft cung cấp kèm, như reporting services, integration services, jobs, tích hợp AD, service broker.
notify/listenkhông có kiểu thông điệpChúng tôi không còn dùng analysis services nữa, nhưng hồi còn dùng thì thứ đó cũng sẽ rất khó thay thế
Những thứ này giữ chân người ta. Tôi thậm chí không hình dung được sẽ mất bao lâu để thay thế tất cả, và bỏ ra 1 năm chỉ để thay thế những thứ đã có sẵn thì tỷ suất lợi nhuận trên đầu tư không tốt
Tôi thắc mắc tại sao nội dung này được công bố trên citusdata chứ không phải postgresql.org. Không rõ đây là tính năng chỉ dành cho bản trả phí hay là bổ sung mã nguồn mở
Khi nào thì có thể dùng index để tăng tốc truy vấn
IS NOT DISTINCT FROMnhỉ ;)