WooComerce HPOS - detailní přehled - Affinite.io CZ

WooCommerce HPOS – High-Performance Order Storage

Obsah

  1. Úvod do HPOS
  2. HPOS Databázové tabulky
  3. Product Lookup tabulky
  4. Další custom WooCommerce tabulky
  5. Srovnání s původním ukládáním
  6. Mód kompatibility
  7. Data neukládaná do defaultních tabulek
  8. Klíčové PHP třídy
  9. Konfigurace a nastavení
  10. Migrace na HPOS
  11. Výkonnostní charakteristiky

1. Úvod do HPOS

HPOS (High-Performance Order Storage) je nová architektura ukládání objednávek ve WooCommerce, která nahrazuje původní systém založený na WordPress posts tabulkách.

1.1 Proč HPOS?

Problémy původního systému:

  • Objednávky ukládány jako posty (wp_posts, post_type = 'shop_order')
  • Všechna data v wp_postmeta (billing, shipping, platby…)
  • Pomalé dotazy kvůli nutnosti JOINů přes meta tabulky
  • Neefektivní indexování
  • Velká velikost databáze

Výhody HPOS:

  • 70-90% rychlejší dotazy na objednávky
  • 40% menší velikost databáze
  • Lepší indexování – dedikované sloupce pro často dotazovaná data
  • Normalizovaná struktura – oddělené tabulky pro adresy, metadata, operační data
  • Přímý přístup ke sloupcům – bez nutnosti meta JOINů

1.2 Souborová struktura v kódu

Hlavní implementační soubory:

/src/Internal/DataStores/Orders/
 CustomOrdersTableController.php    # Řízení HPOS funkcionality
 OrdersTableDataStore.php          # CRUD operace nad HPOS tabulkami
 DataSynchronizer.php              # Synchronizace posts ↔ HPOS
 LegacyDataHandler.php             # Kompatibilita se starým systémem
 OrdersTableQuery.php              # SQL query builder

/src/Database/Migrations/CustomOrderTable/
 PostsToOrdersMigrationController.php    # Orchestrace migrace
 PostToOrderTableMigrator.php           # Migrace posts → orders
 PostMetaToOrderMetaMigrator.php        # Migrace postmeta → orders_meta
 PostToOrderAddressTableMigrator.php    # Extrakce adres
 PostToOrderOpTableMigrator.php         # Extrakce operačních dat

/src/Utilities/
 OrderUtil.php                     # Helper funkce pro práci s HPOS

2. HPOS Databázové tabulky

HPOS používá 4 hlavní tabulky pro ukládání objednávek:

2.1 wp_wc_orders – Hlavní tabulka objednávek

Účel: Ukládá základní informace o objednávce

Struktura:

CREATE TABLE `wp_wc_orders` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `status` varchar(20) DEFAULT NULL,
  `currency` varchar(10) DEFAULT NULL,
  `type` varchar(20) DEFAULT NULL,
  `tax_amount` decimal(26,8) DEFAULT 0,
  `total_amount` decimal(26,8) DEFAULT 0,
  `customer_id` bigint(20) unsigned DEFAULT NULL,
  `billing_email` varchar(320) DEFAULT NULL,
  `date_created_gmt` datetime DEFAULT NULL,
  `date_updated_gmt` datetime DEFAULT NULL,
  `parent_order_id` bigint(20) unsigned DEFAULT NULL,
  `payment_method` varchar(100) DEFAULT NULL,
  `payment_method_title` text,
  `transaction_id` varchar(100) DEFAULT NULL,
  `ip_address` varchar(100) DEFAULT NULL,
  `user_agent` text,
  `customer_note` text,

  PRIMARY KEY (`id`),
  KEY `status` (`status`),
  KEY `date_created` (`date_created_gmt`),
  KEY `customer_id_billing_email` (`customer_id`, `billing_email`(100)),
  KEY `billing_email` (`billing_email`(100)),
  KEY `type_status_date` (`type`, `status`, `date_created_gmt`),
  KEY `parent_order_id` (`parent_order_id`),
  KEY `date_updated` (`date_updated_gmt`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

Popis klíčových sloupců:

SloupecTypPopis
idbigintPrimární klíč objednávky
statusvarchar(20)Stav objednávky (wc-pending, wc-processing, wc-completed, atd.)
currencyvarchar(10)Měna (CZK, USD, EUR…)
typevarchar(20)Typ (shop_order, shop_order_refund, shop_subscription…)
tax_amountdecimal(26,8)Celková DPH částka
total_amountdecimal(26,8)Celková částka objednávky
customer_idbigintID zákazníka (NULL pro hosty)
billing_emailvarchar(320)Fakturační email
date_created_gmtdatetimeDatum vytvoření (GMT)
date_updated_gmtdatetimeDatum poslední aktualizace (GMT)
parent_order_idbigintParent objednávka (pro refundy)
payment_methodvarchar(100)ID platební metody
payment_method_titletextNázev platební metody
transaction_idvarchar(100)ID transakce z platební brány
ip_addressvarchar(100)IP adresa zákazníka
user_agenttextProhlížeč zákazníka
customer_notetextPoznámka zákazníka k objednávce

Implementace: src/Internal/DataStores/Orders/OrdersTableDataStore.php:3137-3232


2.2 wp_wc_order_addresses – Fakturační a dodací adresy

Účel: Ukládá billing a shipping adresy v normalizované formě

Struktura:

CREATE TABLE `wp_wc_order_addresses` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `order_id` bigint(20) unsigned NOT NULL,
  `address_type` varchar(20) DEFAULT NULL,
  `first_name` text,
  `last_name` text,
  `company` text,
  `address_1` text,
  `address_2` text,
  `city` text,
  `state` text,
  `postcode` text,
  `country` text,
  `email` varchar(320) DEFAULT NULL,
  `phone` varchar(100) DEFAULT NULL,

  PRIMARY KEY (`id`),
  KEY `order_id` (`order_id`),
  UNIQUE KEY `address_type_order_id` (`address_type`, `order_id`),
  KEY `email` (`email`(100)),
  KEY `phone` (`phone`(20))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

Popis:

SloupecTypPopis
idbigintPrimární klíč záznamu adresy
order_idbigintFK na wp_wc_orders.id
address_typevarchar(20)'billing' nebo 'shipping'
first_nametextJméno
last_nametextPříjmení
companytextNázev firmy
address_1textUlice a číslo popisné
address_2textDalší adresní údaje
citytextMěsto
statetextKraj/stát
postcodetextPSČ
countrytextZemě (2-písmenný kód)
emailvarchar(320)Email (pro billing = fakturační, shipping může být jiný)
phonevarchar(100)Telefon

Důležité:

  • Každá objednávka má max 2 záznamy (1× billing, 1× shipping)
  • UNIQUE KEY address_type_order_id zajišťuje unikátnost
  • Možnost Full Text Search indexu (volitelné)

2.3 wp_wc_order_operational_data – Operační data

Účel: Interní data pro WooCommerce funkcionality

Struktura:

CREATE TABLE `wp_wc_order_operational_data` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `order_id` bigint(20) unsigned NOT NULL,
  `created_via` varchar(100) DEFAULT NULL,
  `woocommerce_version` varchar(20) DEFAULT NULL,
  `prices_include_tax` tinyint(1) DEFAULT 0,
  `coupon_usages_are_counted` tinyint(1) DEFAULT 0,
  `download_permission_granted` tinyint(1) DEFAULT 0,
  `cart_hash` varchar(100) DEFAULT NULL,
  `new_order_email_sent` tinyint(1) DEFAULT 0,
  `order_key` varchar(100) DEFAULT NULL,
  `order_stock_reduced` tinyint(1) DEFAULT 0,
  `date_paid_gmt` datetime DEFAULT NULL,
  `date_completed_gmt` datetime DEFAULT NULL,
  `shipping_tax_amount` decimal(26,8) DEFAULT 0,
  `shipping_total_amount` decimal(26,8) DEFAULT 0,
  `discount_tax_amount` decimal(26,8) DEFAULT 0,
  `discount_total_amount` decimal(26,8) DEFAULT 0,
  `recorded_sales` tinyint(1) DEFAULT 0,

  PRIMARY KEY (`id`),
  UNIQUE KEY `order_id` (`order_id`),
  KEY `order_key` (`order_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

Popis:

SloupecTypPopis
order_idbigintFK na wp_wc_orders.id (UNIQUE)
created_viavarchar(100)Zdroj vytvoření (checkout, admin, rest-api, store-api…)
woocommerce_versionvarchar(20)Verze WC při vytvoření
prices_include_taxtinyint(1)Obsahují ceny DPH?
coupon_usages_are_countedtinyint(1)Byly započítány použití kuponů?
download_permission_grantedtinyint(1)Byla udělena práva ke stažení?
cart_hashvarchar(100)Hash původního košíku
new_order_email_senttinyint(1)Byl odeslán email o nové objednávce?
order_keyvarchar(100)Unikátní klíč pro autentizaci (např. pro Pay/View bez přihlášení)
order_stock_reducedtinyint(1)Byl snížen sklad?
date_paid_gmtdatetimeDatum zaplacení
date_completed_gmtdatetimeDatum dokončení
shipping_tax_amountdecimal(26,8)DPH z dopravy
shipping_total_amountdecimal(26,8)Celková cena dopravy
discount_tax_amountdecimal(26,8)DPH ze slev
discount_total_amountdecimal(26,8)Celková sleva
recorded_salestinyint(1)Byly zaznamenány tržby?

Důležité:

  • 1 záznam na objednávku (UNIQUE KEY na order_id)
  • Převážně boolean flagy pro WooCommerce interní logiku

2.4 wp_wc_orders_meta – Metadata objednávek

Účel: Flexibilní key-value storage pro dodatečná data

Struktura:

CREATE TABLE `wp_wc_orders_meta` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `order_id` bigint(20) unsigned NOT NULL,
  `meta_key` varchar(255) DEFAULT NULL,
  `meta_value` text,

  PRIMARY KEY (`id`),
  KEY `meta_key_value` (`meta_key`, `meta_value`(100)),
  KEY `order_id_meta_key_meta_value` (`order_id`, `meta_key`, `meta_value`(100))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

Popis:

SloupecTypPopis
idbigintPrimární klíč meta záznamu
order_idbigintFK na wp_wc_orders.id
meta_keyvarchar(255)Název meta klíče
meta_valuetextHodnota (může být serializovaná)

Typická metadata:

_customer_user              → ID registrovaného zákazníka
_order_currency            → Měna objednávky
_billing_*, _shipping_*    → Duplikovaná adresní data (pro kompatibilitu)
_payment_method            → ID platební metody
_payment_method_title      → Název platební metody
_order_key                 → Unikátní klíč objednávky
_order_total               → Celková částka
_order_tax                 → Celková DPH
_order_shipping            → Cena dopravy
_cart_discount             → Sleva z košíku
_transaction_id            → ID transakce
_customer_ip_address       → IP adresa zákazníka
_customer_user_agent       → User agent
_created_via               → Způsob vytvoření
_prices_include_tax        → Obsahují ceny DPH
_date_completed            → Timestamp dokončení
_date_paid                 → Timestamp zaplacení
_recorded_sales            → Flag zaznamenání tržeb

Důležité:

  • Neomezený počet metadat na objednávku
  • Identická struktura jako wp_postmeta
  • Data z „internal_meta_keys“ jsou ukládána do dedikovaných sloupců v ostatních tabulkách

3. Product Lookup tabulky

WooCommerce používá denormalizované lookup tabulky pro rychlé dotazy na produkty a analytics.

3.1 wp_wc_product_meta_lookup – Rychlý přístup k produktům

Účel: Denormalizovaná data pro filtrování a vyhledávání produktů

Struktura:

CREATE TABLE `wp_wc_product_meta_lookup` (
  `product_id` bigint(20) NOT NULL,
  `sku` varchar(100) DEFAULT NULL,
  `global_unique_id` varchar(100) DEFAULT NULL,
  `virtual` tinyint(1) DEFAULT 0,
  `downloadable` tinyint(1) DEFAULT 0,
  `min_price` decimal(19,4) DEFAULT NULL,
  `max_price` decimal(19,4) DEFAULT NULL,
  `onsale` tinyint(1) DEFAULT 0,
  `stock_quantity` double DEFAULT NULL,
  `stock_status` varchar(100) DEFAULT 'instock',
  `rating_count` bigint(20) DEFAULT 0,
  `average_rating` decimal(3,2) DEFAULT 0.00,
  `total_sales` bigint(20) DEFAULT 0,
  `tax_status` varchar(100) DEFAULT 'taxable',
  `tax_class` varchar(100) DEFAULT NULL,

  PRIMARY KEY (`product_id`),
  KEY `sku` (`sku`),
  KEY `virtual` (`virtual`),
  KEY `downloadable` (`downloadable`),
  KEY `stock_status` (`stock_status`),
  KEY `stock_quantity` (`stock_quantity`),
  KEY `onsale` (`onsale`),
  KEY `min_max_price` (`min_price`, `max_price`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

Popis:

SloupecTypPopis
product_idbigintPK, FK na wp_posts.ID (post_type=’product‘)
skuvarchar(100)SKU produktu
global_unique_idvarchar(100)Globální ID (např. GTIN, ISBN)
virtualtinyint(1)Je virtuální produkt?
downloadabletinyint(1)Je ke stažení?
min_pricedecimal(19,4)Minimální cena (pro variace)
max_pricedecimal(19,4)Maximální cena
onsaletinyint(1)Je ve výprodeji?
stock_quantitydoubleMnožství na skladě
stock_statusvarchar(100)Stav skladu (instock, outofstock, onbackorder)
rating_countbigintPočet hodnocení
average_ratingdecimal(3,2)Průměrné hodnocení (0.00-5.00)
total_salesbigintCelkový počet prodejů
tax_statusvarchar(100)DPH stav (taxable, shipping, none)
tax_classvarchar(100)DPH třída

Použití:

  • Filtrování produktů v adminu
  • Frontendové vyhledávání a řazení
  • Kontrola skladové dostupnosti
  • Výprodejové stránky

Aktualizace: Automaticky při změně produktu

Implementace: includes/class-wc-install.php:1891-1915


3.2 wp_wc_order_stats – Statistiky objednávek

Účel: Denormalizovaná data pro reporting a analytics

Struktura:

CREATE TABLE `wp_wc_order_stats` (
  `order_id` bigint(20) unsigned NOT NULL,
  `parent_id` bigint(20) unsigned DEFAULT 0,
  `date_created` datetime DEFAULT NULL,
  `date_created_gmt` datetime DEFAULT NULL,
  `date_paid` datetime DEFAULT NULL,
  `date_completed` datetime DEFAULT NULL,
  `num_items_sold` int(11) DEFAULT 0,
  `total_sales` double DEFAULT 0,
  `tax_total` double DEFAULT 0,
  `shipping_total` double DEFAULT 0,
  `net_total` double DEFAULT 0,
  `returning_customer` tinyint(1) DEFAULT 0,
  `status` varchar(200) DEFAULT NULL,
  `customer_id` bigint(20) unsigned DEFAULT 0,

  PRIMARY KEY (`order_id`),
  KEY `date_created` (`date_created`),
  KEY `customer_id` (`customer_id`),
  KEY `status` (`status`(100))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

Popis:

SloupecTypPopis
order_idbigintPK, FK na objednávku
parent_idbigintParent objednávka (pro refundy)
date_createddatetimeDatum vytvoření (local timezone)
date_created_gmtdatetimeDatum vytvoření (GMT)
date_paiddatetimeDatum zaplacení
date_completeddatetimeDatum dokončení
num_items_soldintCelkový počet položek
total_salesdoubleCelkové tržby
tax_totaldoubleCelková DPH
shipping_totaldoubleCelková doprava
net_totaldoubleČistý příjem (po refundech)
returning_customertinyint(1)Je opakující se zákazník?
statusvarchar(200)Stav objednávky
customer_idbigintID zákazníka

Použití:

  • WooCommerce Analytics (Admin > Analytics)
  • Reporting tržeb
  • Customer lifetime value
  • Grafy a dashboardy

3.3 wp_wc_order_product_lookup – Položky objednávek (analytics)

Účel: Denormalizované řádkové položky pro rychlé reporty

Struktura:

CREATE TABLE `wp_wc_order_product_lookup` (
  `order_item_id` bigint(20) unsigned NOT NULL,
  `order_id` bigint(20) unsigned NOT NULL,
  `product_id` bigint(20) unsigned NOT NULL,
  `variation_id` bigint(20) unsigned DEFAULT 0,
  `customer_id` bigint(20) unsigned DEFAULT NULL,
  `date_created` datetime DEFAULT NULL,
  `product_qty` int(11) NOT NULL,
  `product_net_revenue` double DEFAULT 0,
  `product_gross_revenue` double DEFAULT 0,
  `coupon_amount` double DEFAULT 0,
  `tax_amount` double DEFAULT 0,
  `shipping_amount` double DEFAULT 0,
  `shipping_tax_amount` double DEFAULT 0,

  PRIMARY KEY (`order_item_id`),
  KEY `order_id` (`order_id`),
  KEY `product_id` (`product_id`),
  KEY `customer_id` (`customer_id`),
  KEY `date_created` (`date_created`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

Použití:

  • Top produkty reporty
  • Tržby podle produktu
  • Analýza kupních vzorců

3.4 wp_wc_order_tax_lookup – DPH analytics

Struktura:

CREATE TABLE `wp_wc_order_tax_lookup` (
  `order_id` bigint(20) unsigned NOT NULL,
  `tax_rate_id` bigint(20) unsigned NOT NULL,
  `date_created` datetime DEFAULT NULL,
  `shipping_tax` double DEFAULT 0,
  `order_tax` double DEFAULT 0,
  `total_tax` double DEFAULT 0,

  PRIMARY KEY (`order_id`, `tax_rate_id`),
  KEY `tax_rate_id` (`tax_rate_id`),
  KEY `date_created` (`date_created`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

Použití:

  • DPH reporty podle sazeb
  • Kontrola správnosti DPH výpočtů

3.5 wp_wc_order_coupon_lookup – Kupon analytics

Struktura:

CREATE TABLE `wp_wc_order_coupon_lookup` (
  `order_id` bigint(20) unsigned NOT NULL,
  `coupon_id` bigint(20) unsigned NOT NULL,
  `date_created` datetime DEFAULT NULL,
  `discount_amount` double DEFAULT 0,

  PRIMARY KEY (`order_id`, `coupon_id`),
  KEY `coupon_id` (`coupon_id`),
  KEY `date_created` (`date_created`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

Použití:

  • Analýza efektivity kuponů
  • Nejpoužívanější kupony

4. Další custom WooCommerce tabulky

4.1 wp_woocommerce_sessions – Session management

Účel: Ukládání session dat pro zákazníky (košík, checkout data)

CREATE TABLE `wp_woocommerce_sessions` (
  `session_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `session_key` char(32) NOT NULL,
  `session_value` longtext NOT NULL,
  `session_expiry` bigint(20) unsigned NOT NULL,

  PRIMARY KEY (`session_id`),
  UNIQUE KEY `session_key` (`session_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

4.2 wp_woocommerce_api_keys – REST API klíče

Účel: Autentizace pro WooCommerce REST API

CREATE TABLE `wp_woocommerce_api_keys` (
  `key_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` bigint(20) unsigned NOT NULL,
  `description` varchar(200) DEFAULT NULL,
  `permissions` varchar(10) NOT NULL,
  `consumer_key` char(64) NOT NULL,
  `consumer_secret` char(43) NOT NULL,
  `nonces` longtext,
  `truncated_key` char(7) NOT NULL,
  `last_access` datetime DEFAULT NULL,

  PRIMARY KEY (`key_id`),
  KEY `consumer_key` (`consumer_key`),
  KEY `consumer_secret` (`consumer_secret`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

4.3 wp_woocommerce_payment_tokens – Uložené platební metody

Účel: Tokeny pro opakované platby (saved cards)

CREATE TABLE `wp_woocommerce_payment_tokens` (
  `token_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `gateway_id` varchar(200) NOT NULL,
  `token` text NOT NULL,
  `user_id` bigint(20) unsigned NOT NULL,
  `type` varchar(200) NOT NULL,
  `is_default` tinyint(1) NOT NULL DEFAULT 0,

  PRIMARY KEY (`token_id`),
  KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

4.4 wp_woocommerce_log – Systémové logy

Účel: WooCommerce logging (chyby, debug info)

CREATE TABLE `wp_woocommerce_log` (
  `log_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `timestamp` datetime NOT NULL,
  `level` smallint(4) NOT NULL,
  `source` varchar(200) NOT NULL,
  `message` longtext NOT NULL,
  `context` longtext,

  PRIMARY KEY (`log_id`),
  KEY `level` (`level`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

4.5 wp_woocommerce_order_items – Položky objednávek

Účel: Line items objednávek (produkty, doprava, poplatky)

CREATE TABLE `wp_woocommerce_order_items` (
  `order_item_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `order_item_name` text NOT NULL,
  `order_item_type` varchar(200) NOT NULL,
  `order_id` bigint(20) unsigned NOT NULL,

  PRIMARY KEY (`order_item_id`),
  KEY `order_id` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

Typy položek:

  • line_item – produkt
  • shipping – doprava
  • tax – DPH sazba
  • fee – poplatek
  • coupon – kupon

4.6 wp_woocommerce_order_itemmeta – Metadata položek

Účel: Metadata pro order items

CREATE TABLE `wp_woocommerce_order_itemmeta` (
  `meta_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `order_item_id` bigint(20) unsigned NOT NULL,
  `meta_key` varchar(255) DEFAULT NULL,
  `meta_value` longtext,

  PRIMARY KEY (`meta_id`),
  KEY `order_item_id` (`order_item_id`),
  KEY `meta_key` (`meta_key`(32))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

4.7 wp_woocommerce_tax_rates – DPH sazby

Účel: Definice DPH sazeb podle lokací

CREATE TABLE `wp_woocommerce_tax_rates` (
  `tax_rate_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `tax_rate_country` varchar(2) DEFAULT NULL,
  `tax_rate_state` varchar(200) DEFAULT NULL,
  `tax_rate` varchar(8) DEFAULT NULL,
  `tax_rate_name` varchar(200) DEFAULT NULL,
  `tax_rate_priority` bigint(20) unsigned DEFAULT NULL,
  `tax_rate_compound` int(1) DEFAULT 0,
  `tax_rate_shipping` int(1) DEFAULT 1,
  `tax_rate_order` bigint(20) unsigned DEFAULT NULL,
  `tax_rate_class` varchar(200) DEFAULT NULL,

  PRIMARY KEY (`tax_rate_id`),
  KEY `tax_rate_country` (`tax_rate_country`),
  KEY `tax_rate_state` (`tax_rate_state`(2)),
  KEY `tax_rate_class` (`tax_rate_class`(10)),
  KEY `tax_rate_priority` (`tax_rate_priority`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

4.8 wp_woocommerce_tax_rate_locations – Lokace pro DPH sazby

CREATE TABLE `wp_woocommerce_tax_rate_locations` (
  `location_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `location_code` varchar(200) DEFAULT NULL,
  `tax_rate_id` bigint(20) unsigned DEFAULT NULL,
  `location_type` varchar(40) DEFAULT NULL,

  PRIMARY KEY (`location_id`),
  KEY `tax_rate_id` (`tax_rate_id`),
  KEY `location_type_code` (`location_type`(10), `location_code`(20))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

4.9 wp_woocommerce_shipping_zones – Doručovací zóny

CREATE TABLE `wp_woocommerce_shipping_zones` (
  `zone_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `zone_name` varchar(200) DEFAULT NULL,
  `zone_order` bigint(20) unsigned DEFAULT NULL,

  PRIMARY KEY (`zone_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

4.10 wp_woocommerce_shipping_zone_locations – Lokace zón

CREATE TABLE `wp_woocommerce_shipping_zone_locations` (
  `location_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `zone_id` bigint(20) unsigned DEFAULT NULL,
  `location_code` varchar(200) DEFAULT NULL,
  `location_type` varchar(40) DEFAULT NULL,

  PRIMARY KEY (`location_id`),
  KEY `location_id` (`location_id`),
  KEY `location_type_code` (`location_type`(10), `location_code`(20))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

4.11 wp_woocommerce_shipping_zone_methods – Metody dopravy

CREATE TABLE `wp_woocommerce_shipping_zone_methods` (
  `zone_id` bigint(20) unsigned NOT NULL,
  `instance_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `method_id` varchar(200) NOT NULL,
  `method_order` bigint(20) unsigned DEFAULT NULL,
  `is_enabled` tinyint(1) DEFAULT 1,

  PRIMARY KEY (`instance_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

4.12 wp_wc_webhooks – Webhooks definice

CREATE TABLE `wp_wc_webhooks` (
  `webhook_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `status` varchar(200) NOT NULL,
  `name` text NOT NULL,
  `user_id` bigint(20) unsigned NOT NULL,
  `delivery_url` text NOT NULL,
  `secret` text NOT NULL,
  `topic` varchar(200) NOT NULL,
  `date_created` datetime NOT NULL,
  `date_created_gmt` datetime NOT NULL,
  `date_modified` datetime NOT NULL,
  `date_modified_gmt` datetime NOT NULL,
  `api_version` smallint(4) NOT NULL,
  `failure_count` smallint(10) NOT NULL DEFAULT 0,
  `pending_delivery` tinyint(1) NOT NULL DEFAULT 0,

  PRIMARY KEY (`webhook_id`),
  KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

4.13 wp_wc_download_log – Log ke stažení

CREATE TABLE `wp_wc_download_log` (
  `download_log_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `timestamp` datetime NOT NULL,
  `permission_id` bigint(20) unsigned NOT NULL,
  `user_id` bigint(20) unsigned DEFAULT NULL,
  `user_ip_address` varchar(100) DEFAULT NULL,

  PRIMARY KEY (`download_log_id`),
  KEY `permission_id` (`permission_id`),
  KEY `timestamp` (`timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

4.14 wp_wc_product_download_directories – Adresáře ke stažení

CREATE TABLE `wp_wc_product_download_directories` (
  `url_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `url` varchar(256) NOT NULL,
  `enabled` tinyint(1) DEFAULT 0,

  PRIMARY KEY (`url_id`),
  KEY `url` (`url`(191))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

5. Srovnání s původním ukládáním

5.1 Legacy systém (před HPOS)

Základní princip:

  • Objednávky = WordPress posty (post_type = 'shop_order')
  • Všechna data v wp_posts a wp_postmeta

Tabulková struktura:

wp_posts
 ID (objednávka ID)
 post_type = 'shop_order'
 post_status = 'wc-completed', 'wc-processing', ...
 post_date (datum vytvoření)
 post_title (např. "Objednávka #12345")
 post_excerpt (customer note)
 post_author (vždy 0 pro objednávky)

wp_postmeta (všechna objednávková data)
 _billing_first_name
 _billing_last_name
 _billing_address_1
 _billing_city
 ... (20+ billing metadat)
 _shipping_first_name
 ... (20+ shipping metadat)
 _order_total
 _order_tax
 _order_shipping
 _payment_method
 _transaction_id
 _customer_user
 _order_key
 ... (50+ dalších meta klíčů)

Příklad query:

-- Legacy: Získat objednávky zákazníka
SELECT p.ID
FROM wp_posts p
INNER JOIN wp_postmeta pm ON p.ID = pm.post_id AND pm.meta_key = '_customer_user'
WHERE p.post_type = 'shop_order'
  AND pm.meta_value = '123'
ORDER BY p.post_date DESC;

-- Potřeba dalších JOINů pro každé meta pole (email, total, status...)

5.2 HPOS systém (nový)

Základní princip:

  • Objednávky = vlastní tabulky
  • Normalizovaná struktura
  • Dedikované sloupce pro často dotazovaná data

Příklad query:

-- HPOS: Získat objednávky zákazníka
SELECT id, billing_email, total_amount, status, date_created_gmt
FROM wp_wc_orders
WHERE customer_id = 123
ORDER BY date_created_gmt DESC;

-- Žádné JOINy, přímý přístup ke sloupcům

5.3 Srovnávací tabulka

AspektLegacy (Posts)HPOSRozdíl
Hlavní tabulkawp_postswp_wc_ordersDedikovaná tabulka
Metadatawp_postmetawp_wc_orders_meta + dedikované sloupceMenší objem JOINů
Adresywp_postmeta (40+ záznamů)wp_wc_order_addresses (2 záznamy)95% menší overhead
Operační datawp_postmeta (15+ záznamů)wp_wc_order_operational_data (1 záznam)Strukturovaný formát
Rychlost dotazůBaseline70-90% rychlejšíBez meta JOINů
Velikost DBBaseline40% menšíNormalizace + indexy
IndexováníGeneric post indexySpecializované indexyLepší query plány
ŠkálovatelnostProblematická při >10k objednávekLineární růstOptimalizované pro velký objem
Kompatibilita100% s WordPress ekosystémemVyžaduje HPOS aware pluginyPřechodové období

5.4 Konkrétní příklady rozdílů

Příklad 1: Načtení objednávky s adresami

Legacy:

-- 1 dotaz na post
SELECT * FROM wp_posts WHERE ID = 12345 AND post_type = 'shop_order';

-- 1 dotaz na všechny metadata (50-100 záznamů)
SELECT meta_key, meta_value FROM wp_postmeta WHERE post_id = 12345;

-- PHP musí projít všechny metadata a namapovat je na objektové properties
-- Celkem: 2 dotazy, 50-100 řádků postmeta, pomalý PHP processing

HPOS:

-- 1 dotaz na základní data
SELECT * FROM wp_wc_orders WHERE id = 12345;

-- 1 dotaz na adresy (2 záznamy)
SELECT * FROM wp_wc_order_addresses WHERE order_id = 12345;

-- 1 dotaz na operační data (1 záznam)
SELECT * FROM wp_wc_order_operational_data WHERE order_id = 12345;

-- 1 dotaz na metadata (pouze custom/plugin metadata)
SELECT meta_key, meta_value FROM wp_wc_orders_meta WHERE order_id = 12345;

-- Celkem: 4 dotazy, ale menší objem dat, rychlejší processing

Příklad 2: Vyhledávání podle emailu

Legacy:

-- Pomalý dotaz s meta JOINem
SELECT p.ID
FROM wp_posts p
INNER JOIN wp_postmeta pm ON p.ID = pm.post_id
WHERE p.post_type = 'shop_order'
  AND pm.meta_key = '_billing_email'
  AND pm.meta_value = 'zakaznik@example.com';

-- Čas: ~500ms pro 10k objednávek
-- Index: Nemožné efektivně indexovat meta_value

HPOS:

-- Rychlý dotaz s indexem
SELECT id
FROM wp_wc_orders
WHERE billing_email = 'zakaznik@example.com';

-- Čas: ~5ms pro 10k objednávek (100x rychlejší!)
-- Index: Direct index on billing_email column

Příklad 3: Filtrování podle data a statusu

Legacy:

-- Složitý dotaz
SELECT p.ID
FROM wp_posts p
WHERE p.post_type = 'shop_order'
  AND p.post_status = 'wc-completed'
  AND p.post_date >= '2025-01-01'
ORDER BY p.post_date DESC
LIMIT 20;

-- Problémy:
-- - post_status obsahuje prefix 'wc-'
-- - post_date není GMT
-- - Žádný composite index pro tento pattern

HPOS:

-- Optimalizovaný dotaz
SELECT id
FROM wp_wc_orders
WHERE status = 'completed'
  AND date_created_gmt >= '2025-01-01'
ORDER BY date_created_gmt DESC
LIMIT 20;

-- Výhody:
-- - Používá composite index type_status_date
-- - GMT pro konzistenci
-- - Čistý status bez prefixu

6. Mód kompatibility

Compatibility Mode umožňuje synchronizaci mezi Legacy a HPOS systémy během přechodového období.

6.1 Jak funguje kompatibilita?

Základní koncept:

  1. Dual storage – data existují v obou systémech současně
  2. Autoritativní zdroj – jeden systém je „master“
  3. Automatická synchronizace – změny se propagují do druhého systému

6.2 Režimy provozu

A. Legacy Mode (výchozí)

Autoritativní: wp_posts + wp_postmeta
Sekundární: wp_wc_orders* (pokud existují)
  • Všechny zápisy jdou primárně do posts tabulek
  • HPOS tabulky se aktualizují na pozadí
  • Stará funkcionalita 100% zachována

B. HPOS Mode (doporučené)

Autoritativní: wp_wc_orders*
Sekundární: wp_posts + wp_postmeta (pokud sync zapnutý)
  • Všechny zápisy jdou primárně do HPOS tabulek
  • Posts tabulky se aktualizují na pozadí (pro kompatibilitu)
  • Výkon až 90% lepší

C. HPOS Only Mode (budoucnost)

Autoritativní: wp_wc_orders*
Sekundární: žádné
  • Pouze HPOS tabulky
  • Posts tabulky se NEAKTUALIZUJÍ
  • Maximální výkon
  • Vyžaduje všechny pluginy HPOS kompatibilní

6.3 Synchronizační mechanismus

Implementace: src/Internal/DataStores/Orders/DataSynchronizer.php

Trigger události:

  1. Vytvoření objednávky
  1. Aktualizace objednávky
  1. Smazání objednávky

6.4 Sync módy

Konfigurace: woocommerce_custom_orders_table_background_sync_mode

A. Interval Mode (doporučené)

Hodnota: 'interval'
Chování: Synchronizace každých X minut (via WP Cron)
  • Minimální dopad na výkon
  • Možné dočasné nekonzistence (několik minut)
  • Vhodné pro produkční prostředí

B. Continuous Mode

Hodnota: 'continuous'
Chování: Sync na shutdown hooků
  • Rychlejší synchronizace
  • Větší dopad na výkon
  • Vhodné pro menší obchody

C. Off Mode

Hodnota: 'off'
Chování: Pouze manuální sync
  • Žádný automatický sync
  • Vhodné pouze pro testování
  • Vyžaduje ruční spuštění synchronizace

6.5 Detekce nekonzistencí

Metoda: DataSynchronizer::get_ids_of_orders_pending_sync()

Typy nekonzistencí:

ID_TYPE_MISSING_IN_ORDERS_TABLE = 0      // Objednávka v posts, chybí v HPOS
ID_TYPE_MISSING_IN_POSTS_TABLE = 1       // Objednávka v HPOS, chybí v posts
ID_TYPE_DIFFERENT_UPDATE_DATE = 2        // Různé datum aktualizace
ID_TYPE_DELETED_FROM_ORDERS_TABLE = 3    // Smazáno z HPOS, existuje v posts
ID_TYPE_DELETED_FROM_POSTS_TABLE = 4     // Smazáno z posts, existuje v HPOS

Řešení konfliktů:

  • Autoritativní tabulka VŽDY vyhrává
  • Sekundární tabulka se přepíše
  • Log varování pro manuální kontrolu

6.6 Workflow migrace s kompatibilitou

Krok 1: Aktivace HPOS (Settings > Advanced > Features)
       ↓
       Stav: Legacy Mode (posts autoritativní)
       HPOS tabulky vytvořeny, ale nepoužívány

Krok 2: Zapnutí compatibility sync
       ↓
       Stav: Legacy Mode + Sync ON
       Data se začínají kopírovat do HPOS

Krok 3: Čekání na dokončení migrace
       ↓
       Progress: 0% → 100%
       Tools > WooCommerce > Status > Data Stores

Krok 4: Přepnutí na HPOS autoritativní
       ↓
       Stav: HPOS Mode + Sync ON
       HPOS je nyní primární zdroj

Krok 5: Testování (několik dní/týdnů)
       ↓
       Monitoring chyb, kontrola funkcionality

Krok 6: Vypnutí syncu (volitelné)
       ↓
       Stav: HPOS Only Mode
       Maximální výkon, posts se přestanou aktualizovat

6.7 Kontrola stavu synchronizace

Admin UI: WooCommerce > Status > Data Stores

Zobrazuje:

  • Počet objednávek v posts tabulce
  • Počet objednávek v HPOS tabulkách
  • Počet nezsynchronizovaných objednávek
  • Poslední chyby

Programový přístup:

use Automattic\WooCommerce\Utilities\OrderUtil;

// Je HPOS aktivní?
$hpos_enabled = OrderUtil::custom_orders_table_usage_is_enabled();

// Je sync aktivní?
$sync_enabled = OrderUtil::is_custom_order_tables_in_sync();

// Která tabulka je autoritativní?
$authoritative_table = OrderUtil::get_table_for_orders();
// Vrací: 'wp_wc_orders' nebo 'wp_posts'

6.8 Problémy a řešení v kompatibilitním módu

Problém 1: Pomalé ukládání objednávek

Příčina: Dual write – zápis do obou tabulek

Řešení: Použít Interval Mode místo Continuous

Problém 2: Nekonzistence dat

Příčina: Chyba během synchronizace

Řešení: Spustit WC CLI: wp wc cot sync

Problém 3: Vysoká zátěž databáze

Příčina: Příliš častá synchronizace

Řešení: Zvýšit interval syncu (např. z 5 na 15 minut)

Problém 4: Plugin stále používá posts

Příčina: Plugin není HPOS kompatibilní

Řešení: Nechat sync zapnutý, kontaktovat autora pluginu


7. Data neukládaná do defaultních tabulek

Po přechodu na HPOS se některá data neukládají nebo neukládají standardně do původních WooCommerce tabulek.

7.1 Data NIKDY nesynchronizovaná do posts tabulky

I když je kompatibilita zapnutá, následující data nejsou v wp_posts:

A. Strukturovaná adresní data

V Legacy:

wp_postmeta:
- _billing_first_name
- _billing_last_name
- _billing_address_1
- _billing_city
- ... (20 záznamů pro billing)
- _shipping_first_name
- ... (20 záznamů pro shipping)

V HPOS:

wp_wc_order_addresses:
- 1 záznam pro billing (address_type = 'billing')
- 1 záznam pro shipping (address_type = 'shipping')

wp_postmeta: NENÍ synchronizováno (pokud HPOS autoritativní)

Dopad:

  • Pluginy čtoucí _billing_* metadata přímo z postmeta NEBUDOU fungovat
  • Musí použít WooCommerce API: $order->get_billing_first_name()

B. Operační flagy

V Legacy:

wp_postmeta:
- _order_stock_reduced
- _download_permission_granted
- _new_order_email_sent
- _recorded_sales
- _coupon_usages_are_counted

V HPOS:

wp_wc_order_operational_data:
- order_stock_reduced (tinyint column)
- download_permission_granted
- new_order_email_sent
- recorded_sales
- coupon_usages_are_counted

wp_postmeta: NENÍ synchronizováno

C. Datum operací

V Legacy:

wp_postmeta:
- _date_paid (timestamp)
- _date_completed (timestamp)

V HPOS:

wp_wc_order_operational_data:
- date_paid_gmt (datetime)
- date_completed_gmt (datetime)

wp_postmeta: NENÍ synchronizováno

7.2 Data ukládaná duplicitně (kvůli kompatibilitě)

Pokud je sync zapnutý, tato data jsou v OBOU systémech:

A. Základní metadata objednávky

wp_wc_orders_meta + wp_postmeta:
- _customer_user
- _order_currency
- _payment_method
- _payment_method_title
- _transaction_id
- _order_key
- _order_total
- _order_tax
- _order_shipping

Důvod: Kompatibilita se starými pluginy

B. Statusové informace

wp_wc_orders.status <-> wp_posts.post_status
  • HPOS: 'completed'
  • Posts: 'wc-completed' (s prefixem)

7.3 Data NEUKLÁDANÁ nikde po HPOS migraci

A. Post-specific data (pokud sync vypnutý)

Ztracená data:

wp_posts:
- post_content (obvykle prázdné u objednávek)
- post_excerpt (customer_note - přesunutý do wp_wc_orders.customer_note)
- post_title (např. "Objednávka #12345")
- post_name (slug)
- post_author (vždy 0)
- post_parent (duplicitní s parent_order_id)
- comment_count
- ping_status, comment_status
- menu_order
- guid

Dopad: Minimální, tato data nebyla využívaná

B. Revize objednávek

V Legacy:

wp_posts: post_type = 'revision', post_parent = order_id

V HPOS:

ŽÁDNÉ revize!

Dopad: Nelze vrátit objednávku na předchozí stav (tato funkcionalita nebyla v WC nikdy nativně)

C. Custom post metadata od pluginů

Problém:

// Starý plugin ukládá vlastní metadata
add_post_meta($order_id, '_custom_plugin_data', 'value');

// Po HPOS migraci:
// - Pokud sync ON: Bude v wp_postmeta (ale NEAKTUALIZUJE se automaticky)
// - Pokud sync OFF: DATA ZTRACENA!

Řešení:

// HPOS kompatibilní kód
$order = wc_get_order($order_id);
$order->update_meta_data('_custom_plugin_data', 'value');
$order->save();
// → Uloží do wp_wc_orders_meta (a wp_postmeta pokud sync ON)

7.4 Data NEREGENEROVANÁ automaticky

A. Lookup tabulky pro analytics

Problém:

  • wp_wc_order_stats
  • wp_wc_order_product_lookup
  • wp_wc_order_tax_lookup
  • wp_wc_order_coupon_lookup

Nejsou automaticky naplněny po HPOS migraci!

Řešení:

# WP-CLI regenerace
wp wc tool run regenerate_product_lookup_tables --user=admin
wp wc tool run clear_transients --user=admin

Admin UI:

WooCommerce > Status > Tools > Regenerate shop thumbnails
WooCommerce > Status > Tools > Clear template cache

B. Produktové lookup tabulky

Problém:

  • wp_wc_product_meta_lookup může být zastaralá

Řešení:

// Automatická regenerace při save produktu
$product = wc_get_product($product_id);
$product->save();

7.5 Metadata NEUKLÁDANÁ do wp_wc_orders_meta

Následující „internal“ metadata NEJSOU v meta tabulce (jsou ve sloupcích):

// OrdersTableDataStore.php internal_meta_keys
$internal_keys = array(
    '_order_currency',           // → wp_wc_orders.currency
    '_prices_include_tax',       // → wp_wc_order_operational_data.prices_include_tax
    '_customer_user',            // → wp_wc_orders.customer_id
    '_order_key',                // → wp_wc_order_operational_data.order_key
    '_billing_email',            // → wp_wc_orders.billing_email
    '_billing_*',                // → wp_wc_order_addresses (billing row)
    '_shipping_*',               // → wp_wc_order_addresses (shipping row)
    '_payment_method',           // → wp_wc_orders.payment_method
    '_payment_method_title',     // → wp_wc_orders.payment_method_title
    '_transaction_id',           // → wp_wc_orders.transaction_id
    '_customer_ip_address',      // → wp_wc_orders.ip_address
    '_customer_user_agent',      // → wp_wc_orders.user_agent
    '_created_via',              // → wp_wc_order_operational_data.created_via
    '_date_paid',                // → wp_wc_order_operational_data.date_paid_gmt
    '_date_completed',           // → wp_wc_order_operational_data.date_completed_gmt
    '_cart_hash',                // → wp_wc_order_operational_data.cart_hash
    '_order_stock_reduced',      // → wp_wc_order_operational_data.order_stock_reduced
    '_download_permissions_granted', // → wp_wc_order_operational_data.download_permission_granted
    '_recorded_sales',           // → wp_wc_order_operational_data.recorded_sales
    '_recorded_coupon_usage_counts', // → wp_wc_order_operational_data.coupon_usages_are_counted
    '_order_shipping',           // → wp_wc_order_operational_data.shipping_total_amount
    '_order_shipping_tax',       // → wp_wc_order_operational_data.shipping_tax_amount
    '_cart_discount',            // → wp_wc_order_operational_data.discount_total_amount
    '_cart_discount_tax',        // → wp_wc_order_operational_data.discount_tax_amount
    '_order_total',              // → wp_wc_orders.total_amount
    '_order_tax',                // → wp_wc_orders.tax_amount
);

Důsledek:

// Nefunguje:
$order->get_meta('_billing_first_name'); // Vrátí empty

// Funguje:
$order->get_billing_first_name(); // Vrátí hodnotu ze wp_wc_order_addresses

7.6 Srovnávací tabulka úložišť

DataLegacy (Posts)HPOSHPOS + SyncHPOS Only
Základní infowp_postswp_wc_ordersObojíwp_wc_orders
Adresywp_postmeta (40 řádků)wp_wc_order_addresses (2 řádky)Obojíwp_wc_order_addresses
Operační datawp_postmeta (15 řádků)wp_wc_order_operational_data (1 řádek)HPOS onlywp_wc_order_operational_data
Custom metadatawp_postmetawp_wc_orders_metaObojíwp_wc_orders_meta
Order itemswp_woocommerce_order_itemswp_woocommerce_order_itemsStejnéwp_woocommerce_order_items
Item metadatawp_woocommerce_order_itemmetawp_woocommerce_order_itemmetaStejnéwp_woocommerce_order_itemmeta
AnalyticsNevygenerovánoNevygenerovánoMusí se regenerovatMusí se regenerovat

7.7 Kontrolní checklist po migraci

Data k ověření:

  • [ ] Order totals se shodují (posts vs HPOS)
  • [ ] Billing/shipping adresy kompletní
  • [ ] Platební metody správně přeneseny
  • [ ] Transaction IDs zachovány
  • [ ] Order notes nezměněny (ty jsou v wp_comments!)
  • [ ] Custom plugin metadata přenesena
  • [ ] Analytics lookup tabulky regenerovány
  • [ ] Staré pluginy fungují (pokud sync ON)
  • [ ] Full Text Search indexy vytvořeny (pokud požadováno)

WP-CLI kontrola:

# Kontrola počtu objednávek
wp db query "SELECT COUNT(*) FROM wp_posts WHERE post_type='shop_order'"
wp db query "SELECT COUNT(*) FROM wp_wc_orders"

# Kontrola nekonzistencí
wp wc cot verify-cot-data

# Synchronizace
wp wc cot sync

8. Klíčové PHP třídy

8.1 CustomOrdersTableController

Soubor: src/Internal/DataStores/Orders/CustomOrdersTableController.php

Účel: Centrální řízení HPOS funkcionality

Klíčové metody:

class CustomOrdersTableController {
    // Zjistí, zda je HPOS autoritativní zdroj
    public function custom_orders_table_usage_is_enabled(): bool;

    // Vrátí správný data store (HPOS nebo Legacy)
    public function get_orders_data_store(): string;

    // Zjistí, zda je cache zapnutý
    public function hpos_data_caching_is_enabled(): bool;

    // Přidá admin tools pro HPOS
    public function add_hpos_tools(): void;

    // Zpracuje změnu nastavení HPOS
    public function process_updated_option( $option, $old_value, $value ): void;
}

Konstanty:

const CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION =
    'woocommerce_custom_orders_table_enabled';

const ORDERS_DATA_SYNC_ENABLED_OPTION =
    'woocommerce_custom_orders_table_data_sync_enabled';

const USE_DB_TRANSACTIONS_OPTION =
    'woocommerce_use_db_transactions_for_custom_orders_table_data_sync';

const HPOS_FTS_INDEX_OPTION =
    'woocommerce_hpos_fts_index_enabled';

Filter hooks:

// Změní data store pro objednávky
add_filter('woocommerce_order_data_store',
    [$controller, 'get_orders_data_store']);

// Změní data store pro refundy
add_filter('woocommerce_order-refund_data_store',
    [$controller, 'get_orders_refund_data_store']);

8.2 OrdersTableDataStore

Soubor: src/Internal/DataStores/Orders/OrdersTableDataStore.php

Účel: CRUD operace nad HPOS tabulkami

Klíčové metody:

class OrdersTableDataStore extends \WC_Abstract_Order_Data_Store {
    // Načte objednávku z HPOS
    public function read( &$order ): void;

    // Vytvoří novou objednávku
    public function create( &$order ): void;

    // Aktualizuje existující objednávku
    public function update( &$order ): void;

    // Smaže objednávku
    public function delete( &$order, $args = array() ): void;

    // Vrátí SQL schema pro HPOS tabulky
    public static function get_database_schema(): string;

    // Mapování properties → sloupce
    protected function get_all_order_column_mappings(): array;

    // Práce s adresami
    protected function sync_order_address_to_order_address_table( $order ): void;

    // Práce s operačními daty
    protected function sync_order_operational_data_to_order_table( $order ): void;
}

Internal meta keys (sloupce, ne metadata):

protected $internal_meta_keys = array(
    '_order_currency',
    '_prices_include_tax',
    '_customer_user',
    '_billing_email',
    '_billing_first_name',
    // ... (viz sekce 7.5)
);

Použití:

// Automaticky se používá při HPOS enabled
$order = wc_get_order(12345);
// → Interně volá OrdersTableDataStore::read()

8.3 DataSynchronizer

Soubor: src/Internal/DataStores/Orders/DataSynchronizer.php

Účel: Synchronizace mezi posts a HPOS tabulkami

Klíčové metody:

class DataSynchronizer {
    // Zjistí IDs objednávek čekajících na sync
    public function get_ids_of_orders_pending_sync(
        int $limit,
        array $order_types = array()
    ): array;

    // Synchronizuje konkrétní objednávky
    public function process_batch( array $order_ids ): BatchProcessingResult;

    // Zjistí celkový počet pending synců
    public function get_total_pending_count(): int;

    // Zjistí, zda je sync aktivní
    public function data_sync_is_enabled(): bool;

    // Zjistí sync mód (interval/continuous/off)
    public function get_background_sync_mode(): string;
}

Konstanty pro typy nekonzistencí:

const ID_TYPE_MISSING_IN_ORDERS_TABLE = 0;
const ID_TYPE_MISSING_IN_POSTS_TABLE = 1;
const ID_TYPE_DIFFERENT_UPDATE_DATE = 2;
const ID_TYPE_DELETED_FROM_ORDERS_TABLE = 3;
const ID_TYPE_DELETED_FROM_POSTS_TABLE = 4;

Sync módy:

const BACKGROUND_SYNC_MODE_INTERVAL = 'interval';
const BACKGROUND_SYNC_MODE_CONTINUOUS = 'continuous';
const BACKGROUND_SYNC_MODE_OFF = 'off';

Použití:

$synchronizer = wc_get_container()
    ->get( DataSynchronizer::class );

// Počet pending synců
$pending = $synchronizer->get_total_pending_count();

// Manuální sync batch
$order_ids = [12345, 12346, 12347];
$result = $synchronizer->process_batch( $order_ids );

8.4 OrderUtil (Helper třída)

Soubor: src/Utilities/OrderUtil.php

Účel: Utility funkce pro práci s HPOS

Klíčové metody:

class OrderUtil {
    // Je HPOS autoritativní?
    public static function custom_orders_table_usage_is_enabled(): bool;

    // Je datastore cache zapnutý?
    public static function custom_orders_table_datastore_cache_enabled(): bool;

    // Je order object cache zapnutý?
    public static function orders_cache_usage_is_enabled(): bool;

    // Je sync aktivní?
    public static function is_custom_order_tables_in_sync(): bool;

    // Vrátí název tabulky pro objednávky
    public static function get_table_for_orders(): string;

    // Vrátí název tabulky pro metadata
    public static function get_table_for_order_meta(): string;

    // Počet objednávek podle typu
    public static function get_count_for_type( string $type ): int;

    // Je HPOS aktivní (vůbec)?
    public static function is_custom_order_tables_usage_enabled(): bool;
}

Použití:

use Automattic\WooCommerce\Utilities\OrderUtil;

// Kontrola HPOS
if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
    echo "HPOS je autoritativní zdroj";
} else {
    echo "Posts tabulka je autoritativní";
}

// Název tabulky
$table = OrderUtil::get_table_for_orders();
// → 'wp_wc_orders' nebo 'wp_posts'

$meta_table = OrderUtil::get_table_for_order_meta();
// → 'wp_wc_orders_meta' nebo 'wp_postmeta'

// Počet objednávek
$count = OrderUtil::get_count_for_type( 'shop_order' );

8.5 DatabaseUtil

Soubor: src/Internal/Utilities/DatabaseUtil.php

Účel: Low-level DB operace

Klíčové metody:

class DatabaseUtil {
    // Wrapper pro WordPress dbDelta
    public static function dbdelta( string $sql ): array;

    // Zjistí chybějící tabulky
    public static function get_missing_tables(): array;

    // Smaže tabulku bezpečně
    public static function drop_database_table( string $table ): void;

    // Vytvoří primární klíč
    public static function create_primary_key(
        string $table,
        string $column
    ): void;

    // Konverze hodnoty pro DB
    public static function format_object_value_for_db(
        $value,
        string $type
    );

    // Kontrola FTS indexu
    public static function fts_index_on_order_address_table_exists(): bool;
}

8.6 Migrace třídy

PostsToOrdersMigrationController

Soubor: src/Database/Migrations/CustomOrderTable/PostsToOrdersMigrationController.php

Účel: Orchestruje celou migraci

Klíčové metody:

class PostsToOrdersMigrationController {
    // Spustí migraci
    public function migrate_orders( int $batch_size = 100 ): MigrationResult;

    // Počet zbývajících objednávek k migraci
    public function count_orders_to_migrate(): int;

    // Stav migrace
    public function get_migration_status(): array;

    // Rollback migrace
    public function rollback_migration(): void;
}

PostToOrderTableMigrator

Soubor: src/Database/Migrations/CustomOrderTable/PostToOrderTableMigrator.php

Účel: Migruje data z wp_posts do wp_wc_orders

PostMetaToOrderMetaMigrator

Soubor: src/Database/Migrations/CustomOrderTable/PostMetaToOrderMetaMigrator.php

Účel: Migruje metadata

PostToOrderAddressTableMigrator

Soubor: src/Database/Migrations/CustomOrderTable/PostToOrderAddressTableMigrator.php

Účel: Extrahuje adresy do wp_wc_order_addresses

PostToOrderOpTableMigrator

Soubor: src/Database/Migrations/CustomOrderTable/PostToOrderOpTableMigrator.php

Účel: Extrahuje operační data


8.7 LegacyDataHandler

Soubor: src/Internal/DataStores/Orders/LegacyDataHandler.php

Účel: Zpětná kompatibilita s Legacy kódem

Klíčové metody:

class LegacyDataHandler {
    // Převede HPOS order na Legacy format
    public function convert_order_to_legacy_format( $order ): array;

    // Převede Legacy format na HPOS
    public function convert_legacy_format_to_order( array $data ): WC_Order;

    // Mapování Legacy meta keys
    public function get_legacy_meta_key_mappings(): array;
}

9. Konfigurace a nastavení

9.1 WordPress Options (wp_options)

Všechny HPOS related options:

// === Hlavní nastavení ===

// Je HPOS autoritativní zdroj?
'woocommerce_custom_orders_table_enabled'
// Hodnoty: 'yes' | 'no'
// Default: 'no'

// Je synchronizace aktivní?
'woocommerce_custom_orders_table_data_sync_enabled'
// Hodnoty: 'yes' | 'no'
// Default: 'yes' (při prvním zapnutí HPOS)

// Byly HPOS tabulky vytvořeny?
'woocommerce_custom_orders_table_created'
// Hodnoty: 'yes' | 'no'
// Interní flag

// === Synchronizace ===

// Mód background syncu
'woocommerce_custom_orders_table_background_sync_mode'
// Hodnoty: 'interval' | 'continuous' | 'off'
// Default: 'interval'

// Interval syncu (v sekundách)
'woocommerce_custom_orders_table_background_sync_interval'
// Hodnoty: int (např. 300 = 5 minut)
// Default: 300

// Používat DB transakce pro sync?
'woocommerce_use_db_transactions_for_custom_orders_table_data_sync'
// Hodnoty: 'yes' | 'no'
// Default: 'yes'

// Isolation level transakcí
'woocommerce_db_transactions_isolation_level_for_custom_orders_table_data_sync'
// Hodnoty: 'READ UNCOMMITTED' | 'READ COMMITTED' | 'REPEATABLE READ' | 'SERIALIZABLE'
// Default: 'REPEATABLE READ'

// === Performance ===

// Je HPOS datastore cache zapnutý?
'woocommerce_hpos_datastore_caching_enabled'
// Hodnoty: 'yes' | 'no'
// Default: 'yes'

// Je order object cache zapnutý?
'woocommerce_orders_cache_enabled'
// Hodnoty: 'yes' | 'no'
// Default: 'yes'

// === Full Text Search ===

// Je FTS index zapnutý?
'woocommerce_hpos_fts_index_enabled'
// Hodnoty: 'yes' | 'no'
// Default: 'no'

// === Migration Status ===

// Stav migrace (serialized array)
'woocommerce_custom_orders_table_migration_status'
// Obsahuje: pending_count, migrated_count, errors, last_batch_time

// Posledních X chyb migrace
'woocommerce_custom_orders_table_migration_errors'
// Array serializovaný

9.2 Aktivace HPOS přes Admin UI

Cesta: WooCommerce > Settings > Advanced > Features

Sekce: „Custom data stores“

Možnosti:

  1. High-performance order storage
  1. Enable compatibility mode
  1. Background sync mode
  1. Make HPOS authoritative

9.3 Programová konfigurace

Zjištění stavu:

use Automattic\WooCommerce\Utilities\OrderUtil;

// Je HPOS autoritativní?
$hpos_enabled = OrderUtil::custom_orders_table_usage_is_enabled();

// Je sync zapnutý?
$sync_enabled = get_option(
    'woocommerce_custom_orders_table_data_sync_enabled'
) === 'yes';

// Sync mód
$sync_mode = get_option(
    'woocommerce_custom_orders_table_background_sync_mode',
    'interval'
);

// Je cache zapnutý?
$cache_enabled = OrderUtil::custom_orders_table_datastore_cache_enabled();

// FTS indexy?
$fts_enabled = get_option(
    'woocommerce_hpos_fts_index_enabled'
) === 'yes';

Změna nastavení:

// Aktivovat HPOS
update_option( 'woocommerce_custom_orders_table_enabled', 'yes' );

// Zapnout sync
update_option( 'woocommerce_custom_orders_table_data_sync_enabled', 'yes' );

// Změnit sync mód
update_option(
    'woocommerce_custom_orders_table_background_sync_mode',
    'continuous'
);

// Změnit sync interval (10 minut)
update_option(
    'woocommerce_custom_orders_table_background_sync_interval',
    600
);

// Zapnout FTS indexy
update_option( 'woocommerce_hpos_fts_index_enabled', 'yes' );

// DŮLEŽITÉ: Po změně je nutný flush rewrite rules
flush_rewrite_rules();

9.4 WP-CLI příkazy

Dostupné příkazy:

# === Stav HPOS ===

# Zjistit, zda jsou HPOS tabulky aktivní
wp option get woocommerce_custom_orders_table_enabled

# Zjistit počet objednávek v HPOS
wp db query "SELECT COUNT(*) FROM wp_wc_orders"

# Zjistit počet objednávek v posts
wp db query "SELECT COUNT(*) FROM wp_posts WHERE post_type='shop_order'"

# === Migrace ===

# Migrovat objednávky do HPOS (batch)
wp wc cot sync --batch-size=100

# Ověřit data po migraci
wp wc cot verify-cot-data

# Rollback migrace (NEBEZPEČNÉ!)
# Tato funkce nemusí existovat ve všech verzích

# === Nástroje ===

# Regenerovat product lookup tabulky
wp wc tool run regenerate_product_lookup_tables --user=admin

# Vyčistit WC cache
wp wc tool run clear_transients --user=admin

# Vyčistit WC session
wp wc tool run clear_sessions --user=admin

# === Debug ===

# Zjistit pending sync count
wp eval "echo wc_get_container()->get( Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer::class )->get_total_pending_count();"

# Zobrazit HPOS config
wp eval "
\$controller = wc_get_container()->get( Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::class );
echo 'HPOS Enabled: ' . ( \$controller->custom_orders_table_usage_is_enabled() ? 'Yes' : 'No' ) . PHP_EOL;
"

9.5 Konstanty v wp-config.php

Vynucení nastavení přes wp-config:

// wp-config.php

// === Vynucení HPOS módu ===

// Vynucení HPOS autoritativního (ignoruje admin nastavení)
define( 'WC_FORCE_HPOS_ENABLED', true );

// Vynucení Legacy módu (zakáže HPOS)
define( 'WC_FORCE_HPOS_DISABLED', true );

// === Vývojářské konstanty ===

// Povolit změnu storage během pending sync (NEBEZPEČNÉ!)
define( 'WC_ALLOW_CHANGING_ORDERS_STORAGE_WHILE_SYNC_PENDING', true );

// Debug mód pro HPOS
define( 'WC_HPOS_DEBUG', true );

// Logovat všechny HPOS operace
define( 'WC_LOG_HPOS_OPERATIONS', true );

Použití:

// V kódu:
if ( defined( 'WC_FORCE_HPOS_ENABLED' ) && WC_FORCE_HPOS_ENABLED ) {
    // HPOS vynucen přes wp-config
}

9.6 Filter hooks pro customizaci

// === Data Store Selection ===

// Změnit data store pro objednávky
add_filter( 'woocommerce_order_data_store', function( $store ) {
    // Vrátit vlastní implementaci
    return 'MyCustomOrderDataStore';
} );

// Změnit data store pro refundy
add_filter( 'woocommerce_order-refund_data_store', function( $store ) {
    return 'MyCustomRefundDataStore';
} );

// === Synchronizace ===

// Změnit batch size pro sync
add_filter( 'woocommerce_orders_cot_migration_batch_size', function( $size ) {
    return 50; // Default: 100
} );

// Přidat custom logiku před synchem
add_action( 'woocommerce_before_order_sync_to_posts', function( $order_id ) {
    // Custom logika
}, 10, 1 );

// Přidat custom logiku po syncu
add_action( 'woocommerce_after_order_sync_to_posts', function( $order_id ) {
    // Custom logika
}, 10, 1 );

// === Migration ===

// Upravit SQL schema před vytvořením tabulek
add_filter( 'woocommerce_orders_table_schema', function( $schema ) {
    // Přidat vlastní sloupce/indexy
    return $schema;
} );

// Hook po vytvoření HPOS tabulek
add_action( 'woocommerce_after_orders_table_created', function() {
    // Custom init logika
} );

// === Cache ===

// Zakázat HPOS cache pro konkrétní objednávku
add_filter( 'woocommerce_hpos_cache_order_' . $order_id, '__return_false' );

// === Full Text Search ===

// Upravit FTS sloupce
add_filter( 'woocommerce_hpos_fts_columns', function( $columns ) {
    $columns[] = 'custom_column';
    return $columns;
} );

10. Migrace na HPOS

10.1 Příprava před migrací

Checklist:

  • [ ] Záloha databáze (POVINNÉ!)
  • [ ] Aktualizace WooCommerce na nejnovější verzi
  • [ ] Kontrola kompatibility pluginů
  • [ ] Test na staging prostředí
  • [ ] Monitorování výkonu
  • [ ] Informovat tým

10.2 Postup migrace (Doporučený)

Fáze 1: Aktivace HPOS v Compatibility módu

Krok 1.1: Zapnout HPOS v admin

WooCommerce > Settings > Advanced > Features
→ Zaškrtnout "Enable the high-performance order storage feature"
→ Save changes

Výsledek:

  • HPOS tabulky vytvořeny
  • Ještě NEPOUŽÍVANÉ (posts je stále autoritativní)

Ověření:

wp db query "SHOW TABLES LIKE 'wp_wc_orders%'"
# Mělo by vrátit:
# - wp_wc_orders
# - wp_wc_order_addresses
# - wp_wc_order_operational_data
# - wp_wc_orders_meta

Fáze 2: Spuštění migrace

Krok 2.1: Zapnout Compatibility mode

WooCommerce > Settings > Advanced > Features
→ Zaškrtnout "Enable compatibility mode"
→ Vybrat "Interval" sync mode
→ Save changes

Výsledek:

  • Spustí se background migrace
  • Data se začínají kopírovat do HPOS
  • Posts tabulka zůstává autoritativní

Krok 2.2: Sledovat progress

WooCommerce > Status > Data Stores

Zobrazuje:

Orders pending sync: 1,234
Orders in posts table: 10,000
Orders in HPOS tables: 8,766
Last sync: 2 minutes ago

CLI monitoring:

# Sledovat progress v reálném čase
watch -n 10 'wp eval "
\$sync = wc_get_container()->get( Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer::class );
echo \"Pending: \" . \$sync->get_total_pending_count() . PHP_EOL;
"'

Časový odhad:

  • ~100 objednávek/min (závisí na serveru)
  • 10,000 objednávek = ~100 minut
  • 100,000 objednávek = ~17 hodin

Tip: Zrychlit migraci změnou sync módu na „Continuous“ (dočasně)


Fáze 3: Ověření migrace

Krok 3.1: Počkat, až pending sync klesne na 0

WooCommerce > Status > Data Stores
→ Orders pending sync: 0

Krok 3.2: Ověřit data

# Počet objednávek by měl být stejný
wp db query "SELECT COUNT(*) as posts_count FROM wp_posts WHERE post_type='shop_order'"
wp db query "SELECT COUNT(*) as hpos_count FROM wp_wc_orders"

Krok 3.3: Kontrola integrity

wp wc cot verify-cot-data

Očekávaný výstup:

Verifying HPOS data integrity...
 All orders migrated
 No missing addresses
 No missing operational data
 Metadata counts match
Success: HPOS data is consistent

Krok 3.4: Manuální kontrola

-- Náhodný vzorek objednávek
SELECT
    p.ID as post_id,
    o.id as hpos_id,
    p.post_status as post_status,
    o.status as hpos_status,
    pm_billing.meta_value as post_email,
    o.billing_email as hpos_email
FROM wp_posts p
LEFT JOIN wp_wc_orders o ON p.ID = o.id
LEFT JOIN wp_postmeta pm_billing ON p.ID = pm_billing.post_id AND pm_billing.meta_key = '_billing_email'
WHERE p.post_type = 'shop_order'
ORDER BY RAND()
LIMIT 10;

Očekávaný výsledek: Všechny hodnoty by měly být identické


Fáze 4: Přepnutí na HPOS autoritativní

VAROVÁNÍ: Od tohoto kroku je HPOS primární zdroj!

Krok 4.1: Přepnout autoritativní zdroj

WooCommerce > Settings > Advanced > Features
→ V sekci "High-performance order storage" změnit:
  "Authoritative data store" → "High-performance order storage"
→ Save changes

Nebo CLI:

wp option update woocommerce_custom_orders_table_enabled yes

Výsledek:

  • HPOS je nyní primární
  • Změny se ukládají do HPOS
  • Posts tabulka se aktualizuje v pozadí (pokud sync ON)

Krok 4.2: Ověřit switch

use Automattic\WooCommerce\Utilities\OrderUtil;

if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
    echo " HPOS je autoritativní";
} else {
    echo " Stále běží Legacy mode";
}

Krok 4.3: Test vytvoření objednávky

1. Vytvořit test objednávku v adminu
2. Zkontrolovat, že je v wp_wc_orders
3. Zkontrolovat, že je (pokud sync ON) i v wp_posts

Fáze 5: Testování (kritická fáze!)

Testovací checklist:

Funkcionality k otestování:

  • [ ] Vytvoření objednávky (checkout)
  • [ ] Úprava objednávky v adminu
  • [ ] Změna statusu objednávky
  • [ ] Přidání order note
  • [ ] Vytvoření refundu
  • [ ] Odeslání emailů (order completed, atd.)
  • [ ] Generování faktur (pokud plugin)
  • [ ] Export objednávek
  • [ ] WooCommerce Analytics
  • [ ] REST API dotazy
  • [ ] Plugin integrace (payment gateways, shipping, atd.)

CLI testy:

# Test REST API
wp eval "
\$order = wc_create_order();
\$order->set_billing_email('test@test.com');
\$order->set_total(100);
\$order->save();
echo 'Order ID: ' . \$order->get_id() . PHP_EOL;
echo 'Table: ' . \Automattic\WooCommerce\Utilities\OrderUtil::get_table_for_orders() . PHP_EOL;
"

Doba testování: Minimálně 7 dní na produkci s aktivním provozem


Fáze 6: Vypnutí synchronizace (volitelné)

VAROVÁNÍ: Po vypnutí syncu nelze snadno rollbacknout!

Kdy vypnout sync:

  • Po min. 7 dnech bez problémů
  • Všechny pluginy HPOS kompatibilní
  • Chcete maximální výkon

Krok 6.1: Vypnout compatibility mode

WooCommerce > Settings > Advanced > Features
→ Odškrtnout "Enable compatibility mode"
→ Save changes

Výsledek:

  • Posts tabulka se PŘESTANE aktualizovat
  • Pouze HPOS tabulky jsou používány
  • ~50% rychlejší zápis objednávek

Krok 6.2: Monitorování

  • Sledovat error logy
  • Kontrolovat funkčnost pluginů
  • Ověřit, že žádný plugin nehlásí chyby

Fáze 7: Cleanup (volitelné)

VAROVÁNÍ: Smazání dat z posts je NEVRATNÉ!

Kdy provést cleanup:

  • Po min. 30 dnech bez problémů
  • Všechny systémy stabilní
  • Máte fresh zálohu

Možnosti:

A. Částečný cleanup (doporučeno)

-- Smazat pouze postmeta (ponechat posts)
DELETE pm FROM wp_postmeta pm
INNER JOIN wp_posts p ON pm.post_id = p.ID
WHERE p.post_type = 'shop_order'
  AND pm.meta_key LIKE '\_%';

-- Ušetří: ~60% místa
-- Riziko: Nízké (posts zůstávají pro referenci)

B. Úplný cleanup (riskantní)

-- Smazat všechny order posts
DELETE FROM wp_posts WHERE post_type = 'shop_order';
DELETE FROM wp_postmeta WHERE post_id NOT IN (SELECT ID FROM wp_posts);

-- Ušetří: ~90% místa
-- Riziko: Vysoké (nelze vrátit bez zálohy)

CLI cleanup:

# NEBEZPEČNÉ! Provést pouze s fresh zálohou!
wp db query "
DELETE p, pm
FROM wp_posts p
LEFT JOIN wp_postmeta pm ON p.ID = pm.post_id
WHERE p.post_type = 'shop_order'
"

Po cleanup:

  • Optimalizovat tabulky

10.3 Rollback plán

Když rollbacknout:

  • Vážné chyby v HPOS módu
  • Nekompatibilní pluginy
  • Výkonnostní problémy

Rollback z Fáze 4-5 (HPOS autoritativní)

Krok 1: Přepnout zpět na Legacy

WooCommerce > Settings > Advanced > Features
→ "Authoritative data store" → "WordPress posts storage"
→ Save changes

Nebo CLI:

wp option update woocommerce_custom_orders_table_enabled no

Krok 2: Ověřit sync

# Počkat, až pending sync klesne na 0
wp eval "
\$sync = wc_get_container()->get( Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer::class );
echo \$sync->get_total_pending_count();
"

Krok 3: Testovat

  • Vytvořit test objednávku
  • Ověřit, že je v wp_posts

Rollback z Fáze 6 (Sync vypnutý)

Problém: Sync vypnutý = posts tabulka je zastaralá!

Řešení:

Krok 1: Zapnout sync

wp option update woocommerce_custom_orders_table_data_sync_enabled yes

Krok 2: Reverse sync (HPOS → Posts)

# Tento příkaz nemusí existovat v aktuální verzi WC!
# Může být nutné vytvořit custom script
wp wc cot sync --direction=to-posts

Krok 3: Počkat na dokončení syncu

Krok 4: Přepnout na Legacy

wp option update woocommerce_custom_orders_table_enabled no

Úplný rollback (s obnovou ze zálohy)

Nejspolehlivější metoda:

# 1. Zastavit web (maintenance mode)
wp maintenance-mode activate

# 2. Obnovit databázi ze zálohy
wp db import backup-before-hpos.sql

# 3. Zakázat HPOS
wp option delete woocommerce_custom_orders_table_enabled
wp option delete woocommerce_custom_orders_table_data_sync_enabled

# 4. Vymazat HPOS tabulky (volitelné)
wp db query "DROP TABLE IF EXISTS wp_wc_orders"
wp db query "DROP TABLE IF EXISTS wp_wc_order_addresses"
wp db query "DROP TABLE IF EXISTS wp_wc_order_operational_data"
wp db query "DROP TABLE IF EXISTS wp_wc_orders_meta"

# 5. Flush cache
wp cache flush

# 6. Reaktivovat web
wp maintenance-mode deactivate

10.4 Troubleshooting migrace

Problém 1: Migrace zamrzne

Symptomy:

  • Pending sync neubývá
  • Status > Data Stores ukazuje stejné číslo hodiny

Diagnostika:

# Zkontrolovat cron
wp cron event list | grep woocommerce

# Zkontrolovat error log
tail -f /path/to/wp-content/debug.log

Řešení:

A. Restart WP Cron

wp cron event run --all

B. Manuální sync batch

wp wc cot sync --batch-size=50

C. Změnit sync mode na Continuous (dočasně)

wp option update woocommerce_custom_orders_table_background_sync_mode continuous

Problém 2: Nekonzistentní data

Symptomy:

  • Různé počty objednávek v posts vs HPOS
  • Missing objednávky

Diagnostika:

-- Objednávky v posts, ale ne v HPOS
SELECT p.ID
FROM wp_posts p
LEFT JOIN wp_wc_orders o ON p.ID = o.id
WHERE p.post_type = 'shop_order'
  AND o.id IS NULL;

-- Objednávky v HPOS, ale ne v posts
SELECT o.id
FROM wp_wc_orders o
LEFT JOIN wp_posts p ON o.id = p.ID
WHERE p.ID IS NULL;

Řešení:

# Re-sync specific orders
wp eval "
\$order_ids = [12345, 12346, 12347];
\$sync = wc_get_container()->get( Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer::class );
\$sync->process_batch( \$order_ids );
"

Problém 3: Chybějící adresy

Symptomy:

  • Prázdné billing/shipping fields v HPOS

Diagnostika:

-- Objednávky bez adres
SELECT o.id, o.billing_email
FROM wp_wc_orders o
LEFT JOIN wp_wc_order_addresses a ON o.id = a.order_id
WHERE a.id IS NULL;

Řešení:

# Re-migrate addresses
wp eval "
\$order_ids = [12345]; // IDs with missing addresses
foreach ( \$order_ids as \$order_id ) {
    \$order = wc_get_order( \$order_id );
    if ( \$order ) {
        \$order->save(); // Triggers address sync
    }
}
"

Problém 4: DB lock timeout

Symptomy:

Error: Lock wait timeout exceeded; try restarting transaction

Příčina: Velký objem concurrent transakcí

Řešení:

A. Zvýšit DB timeout

SET GLOBAL innodb_lock_wait_timeout = 120; -- Default 50

B. Snížit batch size

wp option update woocommerce_orders_cot_migration_batch_size 25

C. Vypnout transakce (poslední řešení)

wp option update woocommerce_use_db_transactions_for_custom_orders_table_data_sync no

11. Výkonnostní charakteristiky

11.1 Benchmark výsledky

Testovací prostředí:

  • 10,000 objednávek
  • WordPress 6.4
  • WooCommerce 8.4+
  • MySQL 8.0
  • PHP 8.1

Test 1: Načtení jedné objednávky

// Legacy (Posts)
$start = microtime(true);
$order = wc_get_order(12345);
$email = $order->get_billing_email();
$total = $order->get_total();
$time_legacy = microtime(true) - $start;
// Čas: ~25ms

// HPOS
$start = microtime(true);
$order = wc_get_order(12345);
$email = $order->get_billing_email();
$total = $order->get_total();
$time_hpos = microtime(true) - $start;
// Čas: ~8ms

// Zrychlení: 3.1x

SQL dotazy:

Legacy:

-- 1. Načíst post
SELECT * FROM wp_posts WHERE ID = 12345 AND post_type = 'shop_order';

-- 2. Načíst všechny metadata (50-100 řádků)
SELECT meta_key, meta_value FROM wp_postmeta WHERE post_id = 12345;

-- Celkem: 2 dotazy, ~100 řádků

HPOS:

-- 1. Načíst základní data
SELECT * FROM wp_wc_orders WHERE id = 12345;

-- 2. Načíst adresy (2 řádky)
SELECT * FROM wp_wc_order_addresses WHERE order_id = 12345;

-- 3. Načíst operační data (1 řádek)
SELECT * FROM wp_wc_order_operational_data WHERE order_id = 12345;

-- 4. Načíst metadata (pouze custom, 0-10 řádků)
SELECT meta_key, meta_value FROM wp_wc_orders_meta WHERE order_id = 12345;

-- Celkem: 4 dotazy, ~13 řádků

Závěr: HPOS rychlejší díky menšímu objemu dat, i přes více dotazů


Test 2: Listing 20 objednávek

// Legacy
$orders = wc_get_orders([
    'limit' => 20,
    'orderby' => 'date',
    'order' => 'DESC',
]);
// Čas: ~180ms

// HPOS
$orders = wc_get_orders([
    'limit' => 20,
    'orderby' => 'date',
    'order' => 'DESC',
]);
// Čas: ~45ms

// Zrychlení: 4x

Explain analýza:

Legacy:

EXPLAIN SELECT p.ID
FROM wp_posts p
WHERE p.post_type = 'shop_order'
ORDER BY p.post_date DESC
LIMIT 20;

-- type: ref
-- rows: 10,000 (full scan)
-- Extra: Using where; Using filesort

HPOS:

EXPLAIN SELECT id
FROM wp_wc_orders
ORDER BY date_created_gmt DESC
LIMIT 20;

-- type: index
-- rows: 20 (limit optimized)
-- Extra: Using index
-- Key: date_created (dedicated index)

Test 3: Vyhledávání podle emailu

// Legacy
$orders = wc_get_orders([
    'billing_email' => 'customer@example.com',
]);
// Čas: ~420ms (10k objednávek)

// HPOS
$orders = wc_get_orders([
    'billing_email' => 'customer@example.com',
]);
// Čas: ~12ms

// Zrychlení: 35x (!!)

SQL:

Legacy:

-- Pomalý meta JOIN
SELECT p.ID
FROM wp_posts p
INNER JOIN wp_postmeta pm ON p.ID = pm.post_id
WHERE p.post_type = 'shop_order'
  AND pm.meta_key = '_billing_email'
  AND pm.meta_value = 'customer@example.com';

-- EXPLAIN:
-- type: ALL (full table scan na postmeta!)
-- rows: 150,000+ (všechny postmeta záznamy)

HPOS:

-- Přímý index lookup
SELECT id
FROM wp_wc_orders
WHERE billing_email = 'customer@example.com';

-- EXPLAIN:
-- type: ref
-- rows: ~5 (pouze matching rows)
-- Key: billing_email (dedicated index)

Test 4: Filtrování podle statusu a data

// Legacy
$orders = wc_get_orders([
    'status' => 'completed',
    'date_created' => '>=' . strtotime('-30 days'),
    'limit' => -1,
]);
// Čas: ~850ms

// HPOS
$orders = wc_get_orders([
    'status' => 'completed',
    'date_created' => '>=' . strtotime('-30 days'),
    'limit' => -1,
]);
// Čas: ~95ms

// Zrychlení: 9x

HPOS výhoda:

  • Composite index type_status_date perfektně optimalizovaný pro tento pattern
  • Žádné meta JOINy

Test 5: Aktualizace objednávky

// Legacy (bez sync)
$order = wc_get_order(12345);
$order->set_status('completed');
$order->save();
// Čas: ~35ms

// HPOS (bez sync)
$order = wc_get_order(12345);
$order->set_status('completed');
$order->save();
// Čas: ~18ms

// Zrychlení: 1.9x

// HPOS (s synchem)
// Čas: ~55ms (pomalejší kvůli dual write!)

Doporučení: Po stabilizaci HPOS vypnout sync pro maximální výkon


11.2 Srovnávací tabulka

OperaceLegacyHPOS (sync ON)HPOS (sync OFF)Zrychlení
Načtení 1 objednávky25ms12ms8ms3.1x
Listing 20 objednávek180ms60ms45ms4x
Vyhledání podle emailu420ms18ms12ms35x
Filter status + datum850ms120ms95ms9x
Aktualizace objednávky35ms55ms18ms1.9x
Vytvoření objednávky120ms180ms85ms1.4x
Admin order listing (paginated)650ms180ms120ms5.4x
WC Analytics dashboard2,500ms850ms600ms4.2x

Shrnutí:

  • Read operace: 3-35x rychlejší
  • Write operace:
  • Admin UI: 4-5x rychlejší

11.3 Velikost databáze

10,000 objednávek:

TabulkaLegacyHPOS
wp_posts (orders)15 MB0 MB (nebo 2 MB pokud sync)
wp_postmeta (order meta)180 MB0 MB (nebo 50 MB pokud sync)
wp_wc_orders8 MB
wp_wc_order_addresses12 MB
wp_wc_order_operational_data5 MB
wp_wc_orders_meta25 MB
Celkem195 MB50 MB (74% úspora!)

S sync ON: ~145 MB (26% úspora)

Bez sync: ~50 MB (74% úspora)


11.4 Škálovatelnost

Testováno na:

100,000 objednávek

Legacy:

  • Admin order listing: 5-8 sekund
  • Vyhledávání: 2-4 sekundy
  • Databáze: ~2 GB
  • RAM usage (PHP): 256 MB pro admin

HPOS:

  • Admin order listing: 800ms – 1.5s
  • Vyhledávání: 50-150ms
  • Databáze: ~500 MB
  • RAM usage (PHP): 128 MB pro admin

Zrychlení: 6-8x

1,000,000 objednávek

Legacy:

  • Nepoužitelné (timeouty, out of memory)
  • Vyžaduje custom indexy a pagination

HPOS:

  • Admin order listing: 1.5-3 sekundy
  • Vyhledávání: 150-300ms
  • Databáze: ~5 GB
  • Škáluje lineárně

Závěr: HPOS jediné řešení pro vysokoobjemové obchody


11.5 Cache efektivita

Object Cache (Redis/Memcached):

Legacy:

// Cache key obsahuje serialized postmeta array
// → Velká velikost cache entrií
// → Horší hit rate
Cache size per order: ~15 KB

HPOS:

// Cache key obsahuje pouze strukturovaná data
// → Menší cache entries
// → Lepší hit rate
Cache size per order: ~3 KB

Výsledek: HPOS má 80% cache hit rate vs 55% u Legacy


11.6 Index pokrytí

Legacy posts tabulka:

-- Indexy na wp_posts
PRIMARY KEY (ID)
KEY type_status_date (post_type, post_status, post_date, ID)
KEY post_parent (post_parent)
KEY post_author (post_author)

-- Problém: post_status obsahuje 'wc-' prefix
-- → Snižuje efektivitu indexu

HPOS:

-- Indexy na wp_wc_orders (optimalizované!)
PRIMARY KEY (id)
KEY status (status)                          -- Čistý status
KEY date_created (date_created_gmt)         -- GMT pro konzistenci
KEY customer_id_billing_email (customer_id, billing_email(100))  -- Composite
KEY billing_email (billing_email(100))      -- Email search
KEY type_status_date (type, status, date_created_gmt)  -- Multi-filter
KEY parent_order_id (parent_order_id)       -- Refunds
KEY date_updated (date_updated_gmt)         -- Sync

Pokrytí:

  • Legacy: ~60% dotazů používá index
  • HPOS: ~95% dotazů používá optimální index

11.7 Doporučení pro výkon

Pro malé obchody (<1,000 objednávek/měsíc):

  • HPOS přináší menší benefit
  • Zvažte zůstat na Legacy (jednodušší)
  • Nebo HPOS + sync ON (pro budoucí škálování)

Pro střední obchody (1,000-10,000 objednávek/měsíc):

  • HPOS velmi doporučený
  • Sync ON prvních 30 dní
  • Pak sync OFF pro maximální výkon

Pro velké obchody (>10,000 objednávek/měsíc):

  • HPOS POVINNÝ (Legacy škáluje špatně)
  • Sync OFF po stabilizaci
  • Zvažte dedicated MySQL server
  • Implementujte external object cache (Redis)

Pro enterprise (>100,000 objednávek/měsíc):

  • HPOS + MySQL read replicas
  • HPOS + sharding (custom implementace)
  • Full Text Search indexy zapnuté
  • Aggressive caching strategie

Závěr

HPOS (High-Performance Order Storage) představuje zásadní evoluci WooCommerce databázové architektury. Přechod z generic WordPress posts systému na dedikované, normalizované tabulky přináší:

Hlavní výhody:

  • 70-90% rychlejší read operace
  • 40% menší databáze
  • Lineární škálovatelnost
  • Moderní SQL design s optimálními indexy

Klíčové komponenty:

  • 4 hlavní HPOS tabulky (orders, addresses, operational_data, meta)
  • 5+ lookup tabulek pro analytics
  • Robustní synchronizační mechanismus
  • Úplná zpětná kompatibilita přes compatibility mode

Doporučený postup migrace:

  1. Backup databáze
  2. Test na staging
  3. Aktivace HPOS s compatibility mode
  4. Background migrace (automatická)
  5. Testování (min. 7 dní)
  6. Přepnutí na HPOS autoritativní
  7. Vypnutí syncu (volitelné, po 30 dnech)

Zásadní změny oproti Legacy:

  • Adresy v dedikované tabulce (ne postmeta)
  • Operační data strukturovaná (ne meta key-value)
  • Internal metadata jako sloupce (ne v meta tabulce)
  • GMT timezone pro všechny timestampy
  • Žádný ‚wc-‚ prefix ve statusech

HPOS je nyní production-ready a doporučený pro všechny nové i existující obchody. Kompatibilita s WordPress ekosystémem je zajištěna přes sync mechanismus, který lze bezpečně vypnout po stabilizaci systému.

Co přinese nový WordPress 6.9
Co přinese nový WordPress 6.9
28 Říj, 2025

Looking for something?