Magevanta

您的前端可能快如閃電,但如果您的 管理員網格載入需要 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 以上的商店,管理員網格需要架構變更:

  1. 專用讀取複本供管理員查詢 — 將管理員讀取分離到獨立的 MySQL 執行個體
  2. 以 Elasticsearch 為後端的產品網格 — 以 ES 取代 MySQL 產品網格以獲得即時篩選
  3. 自訂微服務網格 — 將繁重的網格卸載到 Node.js/Python 服務及其自身的索引儲存區
  4. 管理員專用 CDN — 快取已渲染的網格 HTML 30-60 秒(內部工具可接受)

總結

管理員網格效能是生產力的倍增器。小型最佳化會產生複合效應:

  1. 為您最常用的網格篩選條件組合新增複合索引
  2. 將預設 pageSize 從 200 減少到 20-50
  3. 預設隱藏昂貴欄位(縮圖、地址)
  4. 為產品/客戶網格啟用平面目錄資料表
  5. 分塊大量操作以避免 PHP 逾時
  6. 為穩定且讀取繁重的網格快取集合結果
  7. 停用未使用的功能(內嵌編輯、拖放、即時計數)

您的營運團隊會感謝您 — 您的伺服器也會感謝您。