Các kiểu Indexer và định nghĩa
Như ta đã biết, có những xử lý trong Magento rất nặng và cần phải được tối ưu. Ví dụ ta có thể thấy, phần giá của sản phẩm trong Magento rất là phức tạp. Nó sẽ là tập hợp các catalog rule, các special price,discount, tier pricing … Và hàm xử lý để tính toán ra giá của sản phẩm sẽ cần phải tổng hợp tất cả các yếu tố đó để hiện ra trên ngoài website. Vậy nếu như mỗi lần có khách hàng truy cập trên website, giá của sản phẩm lại cần phải tính toán lại, điều đó sẽ gây lãng phí tài nguyên rất nhiều.
Chúng ta cần một giải pháp nào đó để ta có thể chỉ cần tính toán một lần thôi, và các lần sau sẽ không cần phải tính lại nữa, mà sẽ chỉ cần lấy data ra và hiển thị cho người dùng. Ở đây có một giải pháp được magento đưa ra. Đó là ta sẽ tính toán trước và lưu lại trong database ở một bảng. Đó là quá trình Indexing.
Indexing là cách magento chuyển hóa dữ liệu để tăng tốc độ xử lý. Mỗi khi dữ liệu thay đổi, data được chuyển hóa cũng cần cập nhật và reindex lại.
Trong blog này, mình sẽ mô tả luồng hoạt động của quá trình reindex để mọi người có thể hiểu rõ hơn cơ chế reindex trong magento 2.
Các kiểu index trong magento 2:
- Full Reindex: build lại toàn bộ các bảng liên quan đến indexer. Thường dùng khi có một sự thay đổi lớn, ví dụ tạo store mới hoặc tạo customer group mới. Lúc đó sẽ thường xảy ra quá trình Full reindex. Có thể reindex full bất cứ lúc nào sử dụng command line của magento
- Partial Re-index là sẽ build lại bảng chỉ cho những thứ thay đổi. Ví dụ thay đổi 1 thuộc tính của product. Thay vì reindex price cho toàn bộ product, ta chỉ reindex cho product nào mà thay đổi thôi.
Nếu như quá trình Full Re-index chỉ đơn giản là build lại toàn bộ các bảng index, thì Partial indexer sẽ tối ưu hơn quá trình index, khi chỉ một thay đổi nhỏ ta sẽ không cần chạy lại toàn bộ, mà chỉ cần chạy lại phần thay đổi.
Partial reindex flow
Hình ảnh sau đây mô tả quá trình partial reindex:

Khi có data thay đổi, sẽ có 2 trường hợp xảy ra tùy thuộc vào chế độ index. Có hai chế độ index partial, đó là Update on Save và Update on Schedule.
Mọi người có thể check settings đó ở trong magento 2.

- Update on Save - Bảng index được cập nhật ngay lập tức khi có sự thay đổi về data
- Update by Schedule - Bảng index được update theo lịch chay của cron. Được tùy biến trong settings.
Partial Indexer - Update on Save
Setting này có ý nghĩa là sau mỗi lần thay đổi dữ liệu, bảng index được cập nhật ngay lập tức.
Để xử lý sự kiện update on save, magento sẽ chạy ngay reindexRow để update bảng indexer ngay lập tức sau khi xử lý xong một logic khiến dữ liệu bị thay đổi.
vendor/magento/module-catalog/Model/Product.php
ta có thể thấy, sau khi product được save, 'priceReindexCallback' và 'eavReindexCallback', sẽ được gọi và reindex row có id = đúng id của product được save.
Partial Indexer - Update on Schedule
Như ở phía trên, mỗi khi có một product thay đổi thì quá trình reindex row đều xảy ra và reindex cho đúng product có id là product thay đổi. Tuy nhiên, nếu ta có 100 product mà mỗi product này sau khi save đều gọi reindex row, thì ta sẽ có 100 lần chạy reindex. Điều này dẫn tới việc reindex diễn ra lẻ tẻ và không theo một lô. Ta hoàn toàn có thể chạy 1 lần và reindex cho 100 product đồng thời một lúc để tối ưu logic code và hiệu năng. Do đó, giải pháp update on schedule cần phải được cân nhắc. Đó là reindex đồng thời nhiều row sau một khoảng thời gian đã được định sẵn. Mặc dù khi reindex theo schedule, quá trình reindex sẽ không real time, tuy nhiên nó sẽ chấp nhận được nếu schedule theo những interval ngắn (magento reindex sau 1 phút 1 lần).
Cơ chế hoạt động của update on schedule.
NHư ta đã biết, update on schedule sẽ reindex cho hàng loạt các row liền một lúc. Vậy magento xử lý thế nào để lưu lại việc nó cần phải reindex cho những row nào ? Mview sinh ra để giải quyết câu chuyện đó.
Mview sinh ra để quản lý sự thay đổi của các bảng data. Khi có một sự thay đổi về bảng được subcriptions, thì trường giá trị của trường entity_column sẽ được lưu lại ở bảng INDEXER_TABLE_NAME + ‘_cl’ . (catalog_category_product_cl)
Ví dụ index catalog_category_product, khi data trong các bảng subcription của nó thay đổi thì giá trị trường entity_column sẽ được lưu vào bảng catalog_category_product_cl. Bảng đó sẽ chứa version_id và entity_id chứa giá trị id của thực thể cần được reindex. Việc này diễn ra tự động mà không cần phải code do magento đã chèn trigger vào trong mysql cho mỗi sự kiện (INSERT, UPDATE, DELETE).
Ví dụ về trigger insert
BEGIN
INSERT IGNORE INTO `catalog_category_product_cl` (`entity_id`) VALUES (NEW.`entity_id`);
END
Về trigger update:
BEGIN
IF (NEW.`entity_id` <=> OLD.`entity_id`
OR NEW.`attribute_set_id` <=> OLD.`attribute_set_id`
OR NEW.`parent_id` <=> OLD.`parent_id`
OR NEW.`created_at` <=> OLD.`created_at`
OR NEW.`path` <=> OLD.`path`
OR NEW.`position` <=> OLD.`position`
OR NEW.`level` <=> OLD.`level`
OR NEW.`children_count` <=> OLD.`children_count`)
THEN INSERT IGNORE INTO `catalog_category_product_cl` (`entity_id`) VALUES (NEW.`entity_id`);
END IF;
END
Để dễ hiểu, haỹ thử làm theo hướng dẫn sau:
Bật chế độ update on schedule ở phần indexer category products.
Bảng catalog_category_entity trong ví dụ trên được nằm trong subcription ở mview.xml
Hãy thử vào data base và thay đổi giá trị bất kì trong bảng đó. Ở đây mình sẽ chỉ đổi position: từ 0->5 bằng phpmyadmin

Trigger sẽ chạy và giá trị của entity_id = 1 sẽ được đẩy vào bảng catalog_category_product_cl.
Hãy thử check:

Record được tự động them vào bảng catalog category id.
Tương tự với record entity_id = 2

Từ 1-> 5
Trigger lại được kích hoạt và ta không phải làm gì thêm:

TIếp theo cron sẽ được chạy và quét bảng catalog_category_product_cl để thực hiện công việc reindexList. Giá trị truyền vào là mảng các ids. Hàm này sẽ chạy và reindex đồng thời các ids đã được lưu trong bảng changelogs.
Tất nhiên sau khi chạy xong, nó sẽ xóa các giá trị ids đã được reindex.
HI vọng bài viết sẽ giúp mọi người hiểu hơn về Partial indexer trong magento 2. Cảm ơn mọi người đã theo dõi :D