Vấn đềGoogle Apps Script giúp việc tự động hóa Sheets trở nên dễ dàng, nhưng nó không phải là một nguồn tài nguyên vô hạn. Để giữ cho nền tảng ổn định, Google áp đặt các giới hạn thời gian nghiêm ngặt đối với các script. Nếu bạn sử dụng tài khoản @gmail.com tiêu chuẩn, script của bạn phải kết thúc trong vòng 6 phút. Người dùng doanh nghiệp trên Google Workspace có khung thời gian dài hơn là 30 phút.
Bạn có thể sẽ chạm ngưỡng giới hạn này khi tập dữ liệu của mình lớn dần. Việc xử lý 20.000 hàng hoặc thực hiện hàng chục lệnh gọi API bên ngoài thường mất nhiều thời gian hơn mức cho phép. Khi hết thời gian, script sẽ dừng ngay lập tức và để lại lỗi sau:
Exception: Exceeded maximum execution time
Nút thắt cổ chai thực sựThủ phạm thường không phải là khối lượng dữ liệu quá lớn. Thay vào đó, đó là sự "gọi lệnh liên tục" (chattiness) trong mã của bạn. Mỗi khi script của bạn gọi getValue() hoặc setValue(), nó phải gửi một yêu cầu qua mạng đến máy chủ bảng tính. Việc này giống như việc lái xe đến cửa hàng tạp hóa chỉ để mua một quả trứng, lái xe về nhà, rồi ngay lập tức lái xe quay lại để mua quả tiếp theo.
Hãy xem xét mô hình phổ biến nhưng kém hiệu quả này:
// CHẬM: Cách tiếp cận "Từng quả trứng một"
function slowProcess() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const lastRow = sheet.getLastRow();
for (let i = 1; i {
let value = row[0];
return [value * 2];
});
// Một lệnh gọi để ghi lại tất cả
sheet.getRange(1, 2, results.length, 1).setValues(results);
}
Một script trước đây mất 5 phút khi sử dụng getValue() thường có thể hoàn thành trong chưa đầy 5 giây bằng phương pháp xử lý hàng loạt này.
2. Chuỗi thực thi với TriggerĐôi khi xử lý hàng loạt là không đủ, đặc biệt nếu bạn đang lấy dữ liệu từ một API bên ngoài chậm. Trong những trường hợp này, bạn cần thiết kế script của mình để tạm dừng, lưu tiến trình và tiếp tục từ nơi nó đã dừng lại. Sử dụng PropertiesService để lưu trữ "điểm kiểm soát" (checkpoint) và ScriptApp để lập lịch cho lần chạy tiếp theo.
function processInChunks() {
const MAX_TIME = 5 * 60 * 1000; // Khoảng đệm an toàn 5 phút
const startTime = new Date().getTime();
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const props = PropertiesService.getScriptProperties();
const startRow = parseInt(props.getProperty('LAST_ROW') || '1');
const lastRow = sheet.getLastRow();
for (let i = startRow; i MAX_TIME) {
props.setProperty('LAST_ROW', i.toString());
createTrigger();
return; // Thoát an toàn trước khi hết thời gian
}
// Logic nặng ở đây (ví dụ: UrlFetchApp.fetch)
let val = sheet.getRange(i, 1).getValue();
}
props.deleteProperty('LAST_ROW');
cleanUpTriggers();
}
function createTrigger() {
ScriptApp.newTrigger('processInChunks')
.timeBased().after(60000).create();
}
Kiểm tra kết quảĐể đảm bảo hệ thống mới của bạn hoạt động tốt, hãy theo dõi các khu vực sau:
- Lịch sử thực thi (Execution History): Kiểm tra tab "Executions" trong trình soạn thảo. Bạn sẽ thấy nhiều lần chạy ngắn, thành công thay vì một lần chạy dài và thất bại.- Nhật ký thuộc tính (Property Logs): Ghi log
PropertiesService.getScriptProperties().getKeys()để xem bộ đếm hàng của bạn có đang cập nhật chính xác hay không.- Số lượng Trigger: Đảm bảo script của bạn xóa các trigger sau khi hoàn thành. Google giới hạn bạn ở mức 20 trigger cho mỗi script, vì vậy đừng để chúng tích tụ quá nhiều.## Kết luận- Giảm thiểu lệnh gọi API: Tương tác với bảng tính rất tốn kém. Logic bên trong công cụ script thì rất rẻ.- Quy tắc 6 phút: Hãy thiết kế script của bạn theo giới hạn 6 phút ngay từ ngày đầu nếu bạn dự kiến dữ liệu của mình sẽ tăng trưởng.- Điểm kiểm soát (Checkpoints): Sử dụngPropertiesServiceđể cung cấp bộ nhớ cho script của bạn để nó có thể sống sót qua các lần khởi động lại.

