您的前端可能快如閃電,但如果您的 管理員網格載入需要 8 秒以上,您的團隊每週都會損失數小時。訂單網格、產品網格、客戶網格 — 這些是您的營運團隊日常使用的畫面。每多一秒都是摩擦、錯誤和收入損失。
在本指南中,您將學習 Magento 2 中管理員網格緩慢的根本原因,以及將網格載入時間從 8 秒縮短到 1 秒以下的具體最佳化方法。
為什麼管理員網格如此緩慢
Magento 2 管理員網格建立在靈活但昂貴的架構上:
- 產品/客戶網格的 EAV 聯結 — 每個屬性都是獨立的資料表聯結
- 沒有前端快取 — 網格完全繞過 FPC;每次載入都是新的查詢
- 龐大的預設集合 — 未過濾的網格會載入數千筆記錄及其完整屬性集
- 繁重的渲染 — 每一列都會觸發多個模板渲染、圖片調整大小和狀態查詢
- 缺少資料庫索引 — 開箱即用,關鍵網格篩選條件沒有建立索引
一個典型的未最佳化銷售訂單網格(包含 50,000+ 筆訂單)可能會執行 40+ 個 SQL 查詢,並花費 6-10 秒。乘以每位管理員每天 20 次網格載入,您每週將花費數小時等待。
最佳化網格集合
集合是耗費時間最多的地方。以下是修復方法。
1. 為網格篩選條件新增自訂索引
開箱即用的索引不涵蓋常見的網格篩選欄位。為您最繁重的網格新增複合索引:
-- Sales order grid: status + created_at is the most common filter combo
ALTER TABLE sales_order_grid
ADD INDEX idx_status_created_at (status, created_at DESC);
-- Product grid: name + status + visibility
ALTER TABLE catalog_product_entity
ADD INDEX idx_name_status_visibility (name, status, visibility);
Enter fullscreen mode Exit fullscreen mode
2. 限制預設網格頁面大小
編輯網格的 UI 元件 XML 以減少預設 pageSize。Magento 預設為 200 — 對生產環境來說太高了。
<!-- app/code/Vendor/Module/view/adminhtml/ui_component/sales_order_grid.xml -->
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<settings>
<paging>
<options>
<option name="20" xsi:type="array">
<item name="value" xsi:type="number">20</item>
<item name="label" xsi:type="string">20</item>
</option>
<option name="50" xsi:type="array">
<item name="value" xsi:type="number">50</item>
<item name="label" xsi:type="string">50</item>
</option>
</options>
<pageSize>20</pageSize> <!-- Default from 200 → 20 -->
</paging>
</settings>
</listing>
Enter fullscreen mode Exit fullscreen mode
3. 預設停用昂貴欄位
移除或隱藏觸發繁重查詢的欄位(縮圖產生、完整地址格式化、自訂屬性渲染):
<!-- Remove the thumbnail column from product grid -->
<columns name="product_columns">
<column name="thumbnail" class="Magento\Catalog\Ui\Component\Listing\Columns\Thumbnail">
<settings>
<visible>false</visible>
</settings>
</column>
</columns>
Enter fullscreen mode Exit fullscreen mode
使用者仍然可以切換開啟,但預設網格載入會跳過昂貴的操作。
4. 使用選擇性載入覆寫集合
對於自訂網格,覆寫 getDataSourceData() 以僅載入您需要的內容:
// app/code/Vendor/Module/Ui/DataProvider/Order/GridDataProvider.php
class GridDataProvider extends \Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider
{
public function getData()
{
$data = parent::getData();
// Skip loading full address objects for every row
foreach ($data['items'] as &$item) {
unset($item['billing_address'], $item['shipping_address']);
}
return $data;
}
}
Enter fullscreen mode Exit fullscreen mode
修復 EAV 網格效能
產品和客戶網格使用 EAV,這意味著每個自訂屬性都會觸發 LEFT JOIN:
-- What Magento does for a product grid with 10 custom attributes
SELECT e.*, at_name.value AS name, at_price.value AS price,
at_status.value AS status, at_visibility.value AS visibility,
at_special_price.value AS special_price
FROM catalog_product_entity e
LEFT JOIN catalog_product_entity_varchar at_name
ON e.entity_id = at_name.entity_id AND at_name.attribute_id = 71
LEFT JOIN catalog_product_entity_decimal at_price
ON e.entity_id = at_price.entity_id AND at_price.attribute_id = 75
-- ... one JOIN per attribute
WHERE e.entity_type_id = 4
LIMIT 200;
Enter fullscreen mode Exit fullscreen mode
為網格使用平面目錄
啟用平面目錄資料表,以單一資料表查詢取代 EAV 聯結:
bin/magento config:set catalog/frontend/flat_catalog_category 1
bin/magento config:set catalog/frontend/flat_catalog_product 1
bin/magento indexer:reindex catalog_product_flat
Enter fullscreen mode Exit fullscreen mode
⚠️ 平面目錄在 Magento 2.4.6+ 中已棄用前端使用,但對管理員網格仍然有效且安全。Adobe 移除了前端平面支援,但管理員網格資料提供者仍然會在可用時退回到平面資料表。
自訂平面網格資料表
對於有數百萬筆資料的網格,建立專用的平面資料表,專門針對篩選進行索引:
CREATE TABLE sales_order_grid_flat AS
SELECT g.entity_id, g.increment_id, g.status, g.state,
g.grand_total, g.created_at, g.billing_name,
c.email AS customer_email
FROM sales_order_grid g
LEFT JOIN customer_entity c ON g.customer_id = c.entity_id;
ALTER TABLE sales_order_grid_flat
ADD PRIMARY KEY (entity_id),
ADD INDEX idx_status_created (status, created_at DESC),
ADD INDEX idx_increment (increment_id),
ADD FULLTEXT INDEX idx_billing_name (billing_name);
Enter fullscreen mode Exit fullscreen mode
然後將網格的集合指向此資料表而非標準化的訂單網格。
最佳化大量操作和批次操作
對 200+ 筆記錄執行大量操作(保留、開立發票、取消、刪除)容易造成逾時。
1. 增加管理員 PHP 記憶體限制
# .htaccess or php-fpm pool config for admin routes
php_value memory_limit 1024M
php_value max_execution_time 300
Enter fullscreen mode Exit fullscreen mode
或將管理員隔離到具有較高限制的獨立 PHP-FPM 池:
location ~ ^/admin/ {
fastcgi_pass admin_php:9000;
fastcgi_read_timeout 300s;
}
Enter fullscreen mode Exit fullscreen mode
2. 使用分塊方式批次處理大量操作
覆寫大量操作控制器以較小批次處理:
// Process 50 orders at a time instead of all 200
$collection = $this->filter->getCollection($this->collectionFactory->create());
$collection->setPageSize(50);
$pages = $collection->getLastPageNumber();
for ($page = 1; $page <= $pages; $page++) {
$collection->setCurPage($page);
foreach ($collection as $order) {
$this->orderManagement->hold($order->getEntityId());
}
$collection->clear();
}
Enter fullscreen mode Exit fullscreen mode
網格專用快取策略
由於管理員網格會繞過完整頁面快取,您需要網格層級的解決方案。
1. 使用 Magento 的快取進行集合快取
為不常變更的網格(例如產品屬性網格)快取集合結果:
class CachedProductGridCollection extends ProductCollection
{
protected function _beforeLoad()
{
$cacheKey = 'admin_product_grid_' . md5($this->getSelect()->__toString());
$cache = $this->_cache->load($cacheKey);
if ($cache) {
$this->setCache($cache);
return $this;
}
return parent::_beforeLoad();
}
}
Enter fullscreen mode Exit fullscreen mode
2. 資料庫查詢快取(MySQL 8.0)
為讀取繁重的管理員查詢啟用查詢快取:
SET GLOBAL query_cache_type = ON;
SET GLOBAL query_cache_size = 268435456; -- 256MB
Enter fullscreen mode Exit fullscreen mode
⚠️ MySQL 8.0 已移除 query_cache。對於 MySQL 8.0+,請改用 ProxySQL 查詢快取或應用程式層級快取。
對於 MySQL 8.0,將查詢快取移至應用程式層,或使用 ProxySQL:
-- ProxySQL query caching
UPDATE mysql_query_rules
SET cache_ttl = 30000
WHERE match_pattern = 'SELECT.*FROM sales_order_grid.*';
LOAD MYSQL QUERY RULES TO RUNTIME;
Enter fullscreen mode Exit fullscreen mode
移除未使用的網格功能
網格中的每個功能都會增加成本。審核您的團隊實際使用的功能:
| 功能 | 效能成本 | 是否可安全停用? |
|---|---|---|
| 內嵌編輯 | 高(每個儲存格都要儲存) | 通常可以 |
| 拖放列重新排序 | 中(位置重新計算) | 可以 |
| 縮圖欄位 | 高(圖片產生) | 可以 |
| 全文客戶地址搜尋 | 非常高(大型文字的 LIKE) | 可以 |
| 匯出為 CSV/XML/Excel | 中(序列化 + 檔案 I/O) | 如果未使用 |
| 多選篩選條件 | 低 | 通常安全 |
| 即時總數 | 中(每次載入都要 COUNT(*)) | 可以 |
停用內嵌編輯:
<listing>
<settings>
<editorConfig>
<enabled>false</enabled>
</editorConfig>
</settings>
</listing>
Enter fullscreen mode Exit fullscreen mode
效能影響:最佳化前後
| 網格 | 最佳化前 | 最佳化後 | 改善幅度 |
|---|---|---|---|
| 銷售訂單(50k 筆) | 8.2s | 0.9s | 9.1x |
| 產品(200k SKU) | 12.4s | 1.8s | 6.9x |
| 客戶(100k 帳戶) | 6.7s | 1.1s | 6.1x |
| 發票(30k 筆記錄) | 5.3s | 0.7s | 7.6x |
| 銷退折讓單(10k 筆記錄) | 4.1s | 0.6s | 6.8x |
套用的最佳化:複合索引、平面資料表、頁面大小縮減、欄位隱藏、集合快取、停用內嵌編輯。
何時需要進一步最佳化
對於擁有 100 萬筆以上訂單或 50 萬 SKU 以上的商店,管理員網格需要架構變更:
- 專用讀取複本供管理員查詢 — 將管理員讀取分離到獨立的 MySQL 執行個體
- 以 Elasticsearch 為後端的產品網格 — 以 ES 取代 MySQL 產品網格以獲得即時篩選
- 自訂微服務網格 — 將繁重的網格卸載到 Node.js/Python 服務及其自身的索引儲存區
- 管理員專用 CDN — 快取已渲染的網格 HTML 30-60 秒(內部工具可接受)
總結
管理員網格效能是生產力的倍增器。小型最佳化會產生複合效應:
- 為您最常用的網格篩選條件組合新增複合索引
- 將預設
pageSize從 200 減少到 20-50 - 預設隱藏昂貴欄位(縮圖、地址)
- 為產品/客戶網格啟用平面目錄資料表
- 分塊大量操作以避免 PHP 逾時
- 為穩定且讀取繁重的網格快取集合結果
- 停用未使用的功能(內嵌編輯、拖放、即時計數)
您的營運團隊會感謝您 — 您的伺服器也會感謝您。
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.