¥
立即购买

数据库索引策略优化

29 浏览
2 试用
0 购买
Dec 3, 2025更新

本提示词专为数据库管理场景设计,通过系统化分析表结构、查询模式和性能需求,生成精准的索引优化方案。它能够帮助数据库管理员快速识别关键索引字段,推荐合适的索引类型(如B-tree、哈希、全文索引等),并考虑存储效率与查询性能的平衡。适用于OLTP系统、数据仓库及高并发场景,确保索引策略既提升查询速度,又避免过度索引导致的存储开销。

表结构摘要

  • 业务与规模
    • OLTP电商核心库;orders≈1.2亿(+120万/日),order_items≈3.5亿,shipments≈1.2亿,users≈800万;写入≈1.5万行/分钟。
  • 表与关键列
    • users(id PK, email UNIQUE, created_at)
    • orders(id PK, user_id FK→users.id, shop_id, status∈{created,paid,shipped,closed},payment_method,total_amount,created_at,updated_at)
    • order_items(id PK, order_id FK→orders.id, product_id, category_id, quantity, price)
    • shipments(order_id PK/FK→orders.id, ship_status∈{pending,out,delivered},province,city,ship_at)
  • 现有索引
    • orders:PK(id),二级索引(created_at)
    • order_items:二级索引(order_id)
    • shipments:PK(order_id)
  • 查询模式要点
    • 高频筛选/排序:user_id+created_at(倒序)、shop_id+status+created_at(倒序)、created_at区间聚合、根据created_at正序抽取小批量、按order_id联表
    • 低基数字段:status、payment_method、ship_status(建议编码或前缀索引优化宽度)
    • 排序特征:均以created_at排序(asc/desc),可通过有序索引避免filesort

索引推荐列表

说明:

  • 类型均为B-tree,满足主流引擎(InnoDB等)。
  • DESC/ASC在MySQL中可逆序扫描,未强制声明方向,兼容性更好。
  • 若数据库为MySQL,括号内“前缀”长度为建议值;若为PostgreSQL,可直接用完整列或使用生成列做编码。
索引名称 类型 字段(顺序/前缀) 适用查询场景 覆盖性/说明
idx_orders_user_created_at orders B-tree (user_id, created_at) Q1 最近90天用户订单(where user_id=?, created_at>=? 且按created_at desc排序limit) 顺序满足等值→范围→排序;不含status以避免IN导致分段破坏排序,从而避免filesort
idx_orders_shop_status_created_at orders B-tree 方案A:(shop_id, status(2), created_at);方案B:(shop_id, status_code, created_at) Q3 商家后台分页(where shop_id=?, status=?, created_at between ? and ? order by created_at desc limit offset,limit) 低基数status置于第二位做等值过滤;对MySQL建议status前缀2(区分cr/cl/pa/sh),或用生成列status_code TINYINT(更稳妥与省空间)
idx_orders_created_at_paymethod_amount orders B-tree 方案A:(created_at, payment_method(8), total_amount);方案B:(created_at, payment_method_code, total_amount) Q4 对账(按created_at区间group by payment_method,按索引范围扫描);Q5 物流监控(按created_at正序获取小批量) 在MySQL中将total_amount放入索引可使Q4成为近似“索引覆盖”聚合(减少回表);payment_method建议前缀或编码
— 删除冗余 — orders 删除旧的单列索引(created_at) 避免与(created_at, …)复合索引重复 以idx_orders_created_at_paymethod_amount替代
维持:idx_order_items_order_id order_items B-tree (order_id) Q2 订单详情(order_items按order_id访问) 已满足等值连接与批量取明细;如确有高频只读明细可考虑替换为(order_id, product_id, quantity, price)以提高覆盖(见实施建议-可选)
维持:PK_shipments_order_id shipments B-tree (order_id) Q5 物流监控(EXISTS/JOIN按order_id探测一行) 每单一条shipment,PK查找O(1);无需额外索引

备注:

  • 方案A为“前缀索引”策略(MySQL等适用);方案B为“生成列编码”策略(更通用且更省空间)。二者择一,不要同时创建。
  • 不推荐把status放在Q1的索引第二位(如(user_id, status, created_at)),因为status IN会导致多段范围扫描,破坏对created_at的有序性并触发filesort。

性能预期

  • Q1 用户最近订单
    • 走 idx_orders_user_created_at:等值(user_id)→范围(created_at>=)→逆序扫描,ORDER BY created_at desc 原地满足,仅回表取(id,status,total_amount)。limit 50,使回表成本有限。
  • Q2 订单详情
    • orders 走PK(id);order_items 走(order_id)等值,顺序扫描所有行。无需额外索引即可达到稳定性能。
  • Q3 商家分页
    • 走 idx_orders_shop_status_created_at:等值(shop_id,status)→范围(created_at between)→按created_at desc原地分页,避免filesort与大范围回表扫描。对于大offset仍建议应用侧采用“基于游标/上次最大created_at+id”的方式分页以进一步稳定P95。
  • Q4 对账聚合
    • 走 idx_orders_created_at_paymethod_amount:按created_at范围顺序扫描,仅用索引页即可获取payment_method与total_amount进行分组求和,显著减少随机回表与IO。
  • Q5 物流监控
    • 驱动表:orders 按 idx_orders_created_at_paymethod_amount 的前缀(created_at)正序范围扫描,逐条用shipments主键(order_id)探测并判定ship_status='pending',直到凑够limit 500。若pending占比过低导致扫描过多,可启用备选方案(实施建议中的“Q5加速备选”)。

整体权衡

  • 读性能:三条复合索引分别对Q1/Q3/Q4+Q5对口优化,减少排序与回表,满足P95<100ms目标的可行性高。
  • 写放大:orders由“1个二级索引(created_at)”变为“3个二级索引”,每次写入需维护2个新增B-tree。结合写入速率(≈250行/秒),通常仍可控。通过前缀/编码降低索引宽度与页分裂概率;分批上线与可见性验证可将退化控制在目标范围内。

实施建议

一、执行DDL(以MySQL 8.0为例,在线方式;其他主流DB请用对应在线/并发建索引语法)

  1. 可选:,用生成列做编码(更省空间,推荐)
  • 将status/payment_method编码为TINYINT生成列,替代前缀索引方案(若无法改表,跳过本步骤,使用前缀方案)
    • ALTER TABLE orders ADD COLUMN status_code TINYINT GENERATED ALWAYS AS ( case status when 'created' then 1 when 'paid' then 2 when 'shipped' then 3 when 'closed' then 4 end ) STORED, ADD COLUMN payment_method_code TINYINT GENERATED ALWAYS AS ( /* 按实际枚举映射,例如 */ case payment_method when 'card' then 1 when 'paypal' then 2 when 'cod' then 3 else 0 end ) STORED;
  1. 建立新索引(先建新、后删旧;逐个上线并观测)
  • Q1
    • CREATE INDEX idx_orders_user_created_at ON orders(user_id, created_at) ALGORITHM=INPLACE, LOCK=NONE;
  • Q3(二选一)
    • 方案A(前缀):CREATE INDEX idx_orders_shop_status_created_at ON orders(shop_id, status(2), created_at) ALGORITHM=INPLACE, LOCK=NONE;
    • 方案B(编码):CREATE INDEX idx_orders_shop_status_created_at ON orders(shop_id, status_code, created_at) ALGORITHM=INPLACE, LOCK=NONE;
  • Q4/Q5(同上,payment_method二选一)
    • 方案A(前缀):CREATE INDEX idx_orders_created_at_paymethod_amount ON orders(created_at, payment_method(8), total_amount) ALGORITHM=INPLACE, LOCK=NONE;
    • 方案B(编码):CREATE INDEX idx_orders_created_at_paymethod_amount ON orders(created_at, payment_method_code, total_amount) ALGORITHM=INPLACE, LOCK=NONE;
  1. 替换旧索引
  • 确认上述索引稳定使用后,删除冗余单列索引(created_at):
    • ALTER TABLE orders DROP INDEX <旧索引名>;
  1. 可选:order_items覆盖优化(仅当“订单详情”读取列稳定且高频且CPU/IO瓶颈明显)
  • 替换为更覆盖的索引(注意宽索引对3.5亿行的体积影响):
    • ALTER TABLE order_items DROP INDEX <现有order_id索引名>, ADD INDEX idx_order_items_orderid_cov(order_id, product_id, quantity, price) ALGORITHM=INPLACE, LOCK=NONE;

二、上线顺序与回滚

  • 顺序:Q4/Q5索引 → Q1索引 → Q3索引(先覆盖公共created_at路径,降低风险)→ 删除旧索引
  • 每建一条索引后:
    • 使用EXPLAIN与实际执行(EXPLAIN ANALYZE或启用optimizer trace)验证:type=range/const,key为目标索引,rows较小,Extra无Using filesort(Q1/Q3)。
    • 观察写入延迟与TPS变化,若超标,可将新索引标记为INVISIBLE验证对计划影响(MySQL:ALTER TABLE orders ALTER INDEX idx_xxx INVISIBLE)。
  • 回滚:DROP INDEX新建索引或将其设为INVISIBLE恢复到原执行路径。

三、监控与阈值

  • 语句层
    • rows_examined/rows_sent、临时表/外部排序次数、扫描的顺序读比例;P95/P99时延(区分读/写)
    • 针对5条典型语句建立独立指标看板(按1分钟/5分钟粒度)
  • 索引层(MySQL示例)
    • sys.schema_index_statistics:rows_selected/rows_read,确认新索引命中
    • information_schema.INNODB_INDEX_STATS:PCT_USED、LEAF_PAGE_COUNT,观察碎片(PCT_USED长期<70%且快速下滑时考虑重建)
    • Handler_read_next/Handler_read_key,Innodb_buffer_pool_read_requests vs reads(命中率)
    • innodb_btree_page_split/second,观察写放大
  • 容量与预算
    • 估算单条索引项宽度:bigint(8)+datetime(5~8)+(status/payment_method前缀或TINYINT)+ PK(8);采用编码/前缀后可显著降低。
    • 总索引大小目标:≤ 数据表大小的1.5倍。若逼近阈值,优先:
      • 使用编码列(替代前缀);
      • 评估是否需要order_items覆盖索引(多为可选);
      • 监控Q4/Q5是否可接受不把total_amount放入索引(即改为(created_at, payment_method[代码])),牺牲部分覆盖以换空间。

四、统计信息与维护

  • 定期ANALYZE TABLE orders, order_items, shipments(低峰期),保证选择率统计新鲜
  • 对低基数字段(status、payment_method)在MySQL 8可创建直方图以提升选择度估计(可选):
    • ANALYZE TABLE orders UPDATE HISTOGRAM ON status, payment_method WITH 128 BUCKETS;
  • 碎片重建
    • 无需定期“例行重建”。当监控显示某索引PCT_USED较低且查询显著退化时,再考虑:
      • ALTER TABLE … DROP/ADD INDEX(或OPTIMIZE TABLE)离峰执行
  • 应用分页建议
    • Q3/Q1尽量使用“基于游标/上次最大(created_at,id)”的seek分页,减少深分页对索引回表的压力

五、Q5加速备选(仅当pending占比极低、导致扫描过多)

  • 额外索引(与现方案二选一,不默认为必需)
    • CREATE INDEX idx_shipments_status_order ON shipments(ship_status, order_id) ALGORITHM=INPLACE, LOCK=NONE;
  • 将查询改写为以shipments为驱动小批量抓取pending的order_id,再JOIN orders过滤created_at并排序limit 500;如结果集≤几千行,排序开销可控。上线前需以EXPLAIN验证扫描行数与排序代价。

六、写入退化控制(<5%)

  • 先启用“编码列方案”,比前缀索引更省空间与页分裂
  • 索引逐条上线与压测;若写延迟上升接近阈值:
    • 优先保留:idx_orders_user_created_at 与 idx_orders_shop_status_created_at(直面用户与商家侧交互)
    • 评估是否将idx_orders_created_at_paymethod_amount降级为(created_at, payment_method_code)(去掉total_amount覆盖),以减少索引宽度与写放大
    • 确保Buffer Pool大小与IO配置可支撑新增索引页

以上方案紧贴5类典型查询的过滤与排序模式,控制索引数量与宽度,避免冗余,提供可落地的DDL与稳妥的上线/监控策略。

Table structure summary

  • articles (≈25M rows, InnoDB assumed)

    • PK: id (bigint)
    • Important columns for queries: author_id, title (varchar), body (text), language (char(2)), status (enum), category_id (int), published_at (timestamp), updated_at
    • Search: full‑text over title/body; filtering/sorting on status, language, category_id, published_at; author feed by author_id + published_at
  • comments (≈200M rows)

    • PK: id (bigint)
    • Important columns: article_id, user_id, content (text), sentiment, created_at (timestamp)
    • Search: full‑text content; moderation filters by created_at and sorts by created_at desc
  • article_metrics (≈25M rows; frequent updates)

    • PK/FK: article_id
    • Important columns: views, likes, shares, updated_at
    • Query: trending within last 24h, ordered by views desc, joined to articles (status/category)
  • Current indexes: PKs only

Index recommendation list

Index name Type Columns / expression Target queries Notes
ft_articles_en_doc FULLTEXT en_doc (generated: CASE WHEN status='published' AND language='en' THEN CONCAT_WS(' ', title, short_body) END) Q1 (full‑text with filters) Sparse FT index only for published English articles; reduces FT size and avoids cross‑language hits.
idx_articles_pub_en_cat_pubat BTREE status, language, category_id, published_at DESC, id Q1 (filter + sort fallback, candidate prefetch) Supports filter and ORDER BY published_at desc; useful for two‑phase retrieval or non‑FT browse.
idx_articles_author_pub_pubat BTREE author_id, status, published_at DESC, id Q3 (author feed) Satisfies filter and sort; efficient keyset pagination.
ft_comments_content FULLTEXT content Q4 (comment moderation) Enables FT search on comments.
idx_comments_created_at_id BTREE created_at DESC, id Q4 (time filter + sort) Assists time‑only scans and reduces sort work on recent windows; FT + filesort still expected.
idx_metrics_updated_views BTREE updated_at, views DESC, article_id Q2 (trending) Narrows to 24h window and provides top‑views within that set; join uses PK on articles.

Optional, size‑saving expressions

  • articles.short_body (generated): SUBSTRING(body, 1, 2000) stored; used in en_doc to cap FT index size.
  • If multi‑language beyond English is needed, add analogous per‑language generated doc columns and FT indexes only when query patterns require them.

DDL examples (MySQL 8.0+)

  • articles (generated columns + FT)

    • ALTER TABLE articles ADD COLUMN short_body TEXT GENERATED ALWAYS AS (SUBSTRING(body, 1, 2000)) STORED;
    • ALTER TABLE articles ADD COLUMN en_doc TEXT GENERATED ALWAYS AS (CASE WHEN status='published' AND language='en' THEN CONCAT_WS(' ', title, short_body) END) STORED;
    • CREATE FULLTEXT INDEX ft_articles_en_doc ON articles (en_doc);
    • CREATE INDEX idx_articles_pub_en_cat_pubat ON articles (status, language, category_id, published_at DESC, id);
    • CREATE INDEX idx_articles_author_pub_pubat ON articles (author_id, status, published_at DESC, id);
  • comments

    • CREATE FULLTEXT INDEX ft_comments_content ON comments (content);
    • CREATE INDEX idx_comments_created_at_id ON comments (created_at DESC, id);
  • article_metrics

    • CREATE INDEX idx_metrics_updated_views ON article_metrics (updated_at, views DESC, article_id);

Performance expectations

  • Q1 Full‑text with filters

    • Primary access via ft_articles_en_doc. Because en_doc includes only published English rows, the FT search space is reduced; post‑filtering by category_id and published_at is applied on a much smaller candidate set.
    • idx_articles_pub_en_cat_pubat enables an efficient two‑step strategy when needed: first fetch recent IDs by filter/sort, then FT‑filter those IDs (application‑level or with a subquery). This avoids large FT scans for very common terms.
    • ORDER BY published_at desc is not satisfied by the FULLTEXT index; a filesort is expected on the candidate set, which is acceptable when candidate count is bounded (LIMIT 20).
  • Q2 Trending

    • idx_metrics_updated_views prunes to last 24h by range on updated_at and provides rows in a views‑friendly order within that time window. The join to articles is via PK; remaining filters (status/category) are applied post‑join.
    • Expect optimizer to start from article_metrics using idx_metrics_updated_views, apply the time predicate, then join to articles by PK and filter status/category. If the 24h window is large, a filesort on views may still occur; the index minimizes the rows entering the sort.
  • Q3 Author feed

    • idx_articles_author_pub_pubat satisfies WHERE author_id=? AND status='published' and ORDER BY published_at DESC. The index scan returns rows already in order; LIMIT with keyset pagination avoids deep offsets.
  • Q4 Comment moderation

    • ft_comments_content is used to locate matching comments; created_at >= ? reduces the candidate set. ORDER BY created_at desc will be a filesort over FT matches; the time predicate limits sort volume. idx_comments_created_at_id benefits non‑FT scans and complements FT for recent‑only operations.

Index size and write cost considerations

  • The sparse FT index on en_doc avoids indexing drafts/archived and non‑English rows, substantially reducing FT size relative to a global FULLTEXT(title, body).
  • short_body caps FT tokenization cost on large bodies; adjust length (e.g., 1000–4000) to meet recall needs while keeping within the 1.2x index‑to‑data budget.
  • article_metrics adds only one secondary index, containing narrow columns, to keep write amplification low for updates to views/likes/shares.

Implementation guidance

  1. Create and validate indexes (online where possible)
  • Use ALGORITHM=INPLACE/INSTANT when supported to avoid long blocking:
    • Adding generated columns: ALTER TABLE ... ADD COLUMN ... STORED, ALGORITHM=INSTANT;
    • Creating BTREE indexes: CREATE INDEX ... ALGORITHM=INPLACE, LOCK=NONE;
    • FULLTEXT index build is online in InnoDB; schedule during off‑peak.
  • After creation, run ANALYZE TABLE on each affected table to refresh statistics.
  1. Query adjustments (optional, but beneficial)
  • Q1: Switch to MATCH(en_doc) AGAINST (? IN BOOLEAN MODE). This leverages the sparse FT index and avoids scanning non‑published/non‑English rows.
  • Q1 two‑step pattern for very common terms:
    • Step 1: SELECT id FROM articles FORCE INDEX (idx_articles_pub_en_cat_pubat) WHERE status='published' AND language='en' AND category_id IN (?,?) AND published_at BETWEEN ? AND ? ORDER BY published_at DESC LIMIT 2000;
    • Step 2: SELECT id, title, published_at FROM articles WHERE id IN (list_from_step1) AND MATCH(en_doc) AGAINST (? IN BOOLEAN MODE) ORDER BY published_at DESC LIMIT 20;
  • Q2: Allow optimizer to start from article_metrics. If needed, hint: SELECT /*+ SET_VAR(sort_buffer_size=...) */ ... FROM article_metrics m FORCE INDEX (idx_metrics_updated_views) JOIN articles a USING (article_id) WHERE ... ORDER BY m.views DESC LIMIT 50;
  1. Full‑text configuration (MySQL)
  • Review and, if needed, tune:
    • innodb_ft_min_token_size (default 3) and ft_min_word_len (default 4 for MyISAM; InnoDB uses innodb_ft_min_token_size). Align with language needs to avoid excessive index growth.
    • Stopword list: ensure domain‑specific terms are not inadvertently dropped; use a custom stopword list if necessary.
  • For multi‑language beyond English, consider per‑language generated columns and FT indexes only when that language is queried frequently.
  1. Monitoring and validation
  • Use EXPLAIN ANALYZE to verify index usage paths for the four top queries.
  • Track:
    • Handler_read* and Innodb_rows_read to detect table/FT scans.
    • Sort_merge_passes and sort_rows for Q1/Q4 filesorts.
    • Index sizes via information_schema.TABLES and STATISTICS; keep total index size within the <1.2x data limit. If exceeding, reduce short_body length and/or narrow FT coverage.
    • QPS/latency P95 via Performance Schema events_statements_summary_by_digest per query pattern.
  1. Maintenance
  • Rebuild frequency:
    • BTREE: no periodic rebuild needed; monitor fragmentation (DATA_FREE) and only OPTIMIZE TABLE when bloat > 20% and measurable performance impact is observed.
    • FULLTEXT: no routine rebuilds; re‑ANALYZE after large data shifts.
  • Statistics:
    • ANALYZE TABLE articles, comments, article_metrics weekly or after large data churn to keep histograms current (if enabled).
  • Fragmentation:
    • article_metrics is update‑heavy; consider periodic OPTIMIZE TABLE during maintenance if secondary index leaf fragmentation grows and affects read latency.
  1. Rollout plan
  • Stage 1 (non‑intrusive): Add generated columns (articles.short_body, articles.en_doc).
  • Stage 2: Create ft_articles_en_doc; validate Q1 with EXPLAIN and controlled canary traffic.
  • Stage 3: Create BTREE indexes on articles and article_metrics; validate Q2/Q3 plans.
  • Stage 4: Create ft_comments_content and idx_comments_created_at_id; validate Q4 on a recent‑time window.
  • Stage 5: Adjust queries (Q1 to MATCH(en_doc)), deploy two‑step retrieval for high‑fanout categories/terms if needed.
  • Stage 6: Monitor, then refine short_body length and FT tokenization settings to meet the size budget.

Notes on redundancy and constraints

  • Avoid additional indexes on likes/shares individually; they increase write cost without serving listed queries.
  • Do not duplicate (status, category_id, published_at) permutations beyond the two recommended composites; adding both (status, language, category_id, published_at) and (status, category_id, language, published_at) is redundant.
  • No filtered indexes are created beyond what is represented via generated columns (industry‑standard workaround in MySQL).

表構造摘要

  • システム種別:高並行OLTP+近実時レポート/分析。読み取りは直近7–30日が中心。書き込みピーク≈80k行/分。
  • 規模:
    • risk_events ≈5億行(1.1億/日増)
    • devices ≈5千万行
    • ip_reputation ≈300万行
    • user_flags ≈数百万行
  • ストレージエンジン前提:InnoDB(MySQL 8.0想定)
  • 既存インデックス:risk_events(id PK)、devices(device_id PK)
  • 主なクエリパターン:
    • 等値+期間フィルタ+created_at降順+LIMIT(Q1, Q2)
    • 期間+イベント種別+OR条件+join(ip)+降順+LIMIT(Q3)
    • 期間+GROUP BY device_id+count(distinct user_id)(Q4)
  • 制約:インデックス総容量≦テーブル容量、書込劣化≦3%、分割(created_atベース)と分割別索引(物理的局所化)を志向

索引推薦一覧

以下は重複と冗長を避け、典型クエリに直結する最小構成です(risk_eventsのみ)。BTREE前提。DESCは8.0でサポートされていますが、ASCでも最適化は成立します。

インデックス名 種別 カラム順序 適用シナリオ 備考
idx_re_user_created BTREE (user_id, created_at DESC) Q1 リアルタイム稽核 等値(user_id)→期間(created_at)→降順。LIMITによりスキャン短縮。カバリング不要(行数100)。
idx_re_device_created BTREE (device_id, created_at DESC) Q2 デバイス画像 等値(device_id)→期間(created_at)→降順。LIMIT500でもテーブル参照許容。device_idが長いため容量増に留意。
idx_re_eventflag_created BTREE (event_type, flagged, created_at DESC) Q3 連合特性+OR条件 ORを生成列flagged(後述)に正規化。event_type/flaggedは等値→期間→降順。ip結合は行取得後にPK参照。
(オプション)idx_re_created_device_user BTREE (created_at, device_id, user_id) Q4 バッチ統計 直近24hの範囲走査効率化+GROUP集計補助。書込劣化と容量次第で導入可否を判断。まずは分割+実行計画検証を推奨。

補足:

  • Q3のために「flagged」生成列を追加(virtual)。これによりOR条件を等値に変換し、単一インデックスで最適化。
  • ip_reputationはPK(ip)がクラスタ化(InnoDB)されているため追加インデックス不要。

性能予期

  • Q1/Q2:
    • インデックス範囲走査+順序満足(filesort回避)。LIMITにより上位N件のみの読み出し。
    • 直近分割(created_at)によりパーティションプリューニングが働き、探索範囲が短縮。
  • Q3:
    • flaggedによりORが等値化され、(event_type, flagged, created_at)の複合キーを使用した順序付き範囲走査が可能。
    • joinはe.ip→ip_reputation.PKでネストループ。ip_reputationは小規模で主キー参照コスト低。
  • Q4:
    • 分割(created_at日次)で当日パーティションのみを走査。必要に応じてオプションインデックスを追加し、範囲→グループ化の負荷を低減。
  • インデックス容量と書込コスト:
    • 上記3本(オプション除く)で総容量はテーブル容量の上限(≦1.0倍)を目標に収まる構成。特にdevice_idの長さによりidx_re_device_createdが支配的。導入後に容量監視必須。
    • 書込劣化は生成列(単純論理式)+3本のセカンダリで抑制。ピーク時負荷は監視のうえ必要ならQ4用インデックス導入を見合わせ。

実施提案(DDL・展開・ロールバック・監視)

  1. 生成列とインデックス作成(オンライン)
  • 目的:Q3最適化(OR排除)
  • DDL(MySQL 8.0, InnoDB)
    • ALTER TABLE risk_events ADD COLUMN flagged TINYINT(1) GENERATED ALWAYS AS ((decision IN ('review','reject')) OR (risk_score >= 80)) VIRTUAL, ALGORITHM=INPLACE, LOCK=NONE;
    • CREATE INDEX idx_re_eventflag_created ON risk_events (event_type, flagged, created_at DESC) ALGORITHM=INPLACE, LOCK=NONE;
  • ロールバック:DROP INDEX idx_re_eventflag_created; ALTER TABLE risk_events DROP COLUMN flagged;
  1. Q1/Q2向け複合インデックス作成(オンライン)
  • DDL:
    • CREATE INDEX idx_re_user_created ON risk_events (user_id, created_at DESC) ALGORITHM=INPLACE, LOCK=NONE;
    • CREATE INDEX idx_re_device_created ON risk_events (device_id, created_at DESC) ALGORITHM=INPLACE, LOCK=NONE;
  • ロールバック:DROP INDEX idx_re_user_created; DROP INDEX idx_re_device_created;
  1. 時間分割(RANGE COLUMNS(created_at)日次)
  • 方針:直近60–90日を日次分割。パーティションプリューニング+物理的局所化で範囲走査を短縮。InnoDBのセカンダリインデックスは各分割に物理分散(論理定義はグローバル)。
  • 新テーブルを用いた移行(大規模のため推奨)
    • 作成(例:直近90日+MAXVALUE)
      • CREATE TABLE risk_events_v2 LIKE risk_events;
      • ALTER TABLE risk_events_v2 PARTITION BY RANGE COLUMNS (created_at)( PARTITION p20250101 VALUES LESS THAN ('2025-01-02'), ... PARTITION p_max VALUES LESS THAN (MAXVALUE) );
      • 既存インデックス相当をrisk_events_v2へ作成(上記3本)。
    • データ移行:gh-ost または pt-online-schema-change を利用しオンラインコピー(書込継続)。
      例:pt-online-schema-change --alter "PARTITION BY RANGE COLUMNS (created_at) ..." --execute
    • スイッチ:トランザクションメンテナンス短時間の停止ウィンドウでRENAME TABLEで切替。
    • ロールバック:旧risk_eventsを保持し、RENAME TABLEで戻す。
  • 運用(分割の自動追加/削除)
    • 1日1回、新規分割追加+保持期間超の分割DROP。
      例:
      • ALTER TABLE risk_events_v2 ADD PARTITION (PARTITION p20250302 VALUES LESS THAN ('2025-03-03'));
      • ALTER TABLE risk_events_v2 DROP PARTITION p20250101;
    • 直近30–60日を「ホット」、以降はアーカイブテーブルへ移送可(分析専用)。
  1. Q4オプションインデックス(必要時のみ)
  • DDL:
    • CREATE INDEX idx_re_created_device_user ON risk_events (created_at, device_id, user_id) ALGORITHM=INPLACE, LOCK=NONE;
  • 導入条件:EXPLAINで当日分割へのプリューニングが効くが行走査量が多くSLOやバッチ時間を阻害する場合。
  • ロールバック:DROP INDEX idx_re_created_device_user;
  1. クエリの微調整
  • Q3:flagged導入後の推奨クエリ(論理同一)
    • SELECT e.id, e.user_id, e.ip, r.risk_level FROM risk_events e JOIN ip_reputation r ON r.ip = e.ip WHERE e.created_at >= ? AND e.event_type IN ('login','payment') AND e.flagged = 1 ORDER BY e.created_at DESC LIMIT 1000;
  • Q4:分割前提で当日分のみを明示(日次境界の取り扱いを明確化)。
  1. 監視指標(導入前後の比較必須)
  • 実行計画/効用
    • EXPLAIN: type=range/const、key=推奨インデックス名、rows推定、Extraに「Using index」「Using filesort」の有無。
    • パーティションプリューニング確認(EXPLAIN PARTITIONS)。
  • 実行時統計
    • performance_schema: statement/event長、Rows_examined、Sort_merge_passes。
    • sys.schema_index_statistics/schema_table_statistics: 使用頻度、ヒット率。
    • InnoDB: buffer pool hit率、redo/flush量、page splits(information_schema.innodb_index_stats)。
  • 書込影響
    • トランザクションレイテンシ、Insert QPS、InnoDB行ロック/ページラッチ待ち。
  • 容量
    • information_schema.tables/statisticsで各インデックスサイズ、総容量がテーブル容量≦1.0倍に収まっているか。
  1. メンテナンス方針
  • 統計更新:ANALYZE TABLE risk_events(日次〜週次、分割追加/削除後)。
  • 断片化監視:innodb_index_statsのleaf_pagesとsizeを比較、顕著な肥大時のみOPTIMIZE TABLE(メンテ時間確保)。
  • 未使用索引の検出:sys.schema_unused_indexesで90日無使用なら削除検討(必ずクエリ監査と併用)。

DDLまとめ(抜粋)

  • 生成列+Q3用索引:
    • ALTER TABLE risk_events ADD COLUMN flagged TINYINT(1) GENERATED ALWAYS AS ((decision IN ('review','reject')) OR (risk_score >= 80)) VIRTUAL, ALGORITHM=INPLACE, LOCK=NONE;
    • CREATE INDEX idx_re_eventflag_created ON risk_events (event_type, flagged, created_at DESC) ALGORITHM=INPLACE, LOCK=NONE;
  • Q1/Q2用索引:
    • CREATE INDEX idx_re_user_created ON risk_events (user_id, created_at DESC) ALGORITHM=INPLACE, LOCK=NONE;
    • CREATE INDEX idx_re_device_created ON risk_events (device_id, created_at DESC) ALGORITHM=INPLACE, LOCK=NONE;
  • (必要時)Q4用索引:
    • CREATE INDEX idx_re_created_device_user ON risk_events (created_at, device_id, user_id) ALGORITHM=INPLACE, LOCK=NONE;
  • 分割(新テーブルに適用):
    • ALTER TABLE risk_events_v2 PARTITION BY RANGE COLUMNS (created_at)( PARTITION p20250301 VALUES LESS THAN ('2025-03-02'), ..., PARTITION p_max VALUES LESS THAN (MAXVALUE) );

注意事項

  • device_idはVARCHAR(64)で索引サイズが大きいため、容量監視必須。将来的に実運用データが16進IDである場合、BINARY(16)化(正規化)や生成列によるハッシュ短縮などでインデックスフットプリントを削減可能(別途計画)。
  • 分割の導入は大規模再構築を伴うため、オンライン移行ツール(gh-ost/pt-online-schema-change)利用とバックアップ/リハーサル必須。
  • 本提案は提示クエリの実行パターンに基づく最小構成。追加インデックスはEXPLAIN/モニタリングで有効性確認後に限定的に導入してください。

示例详情

解决的问题

把索引设计这件“又急又难”的活,变成可复制的标准流程:在几分钟内,基于你的表结构与常见查询,自动生成一套兼顾提速与成本的索引优化方案;精准识别关键字段和排序/联结需求,给出清晰的索引组合与字段顺序;同时控制索引数量与体积,避免过度建设带来的写入放缓与存储膨胀;最终产出可直接执行的创建清单、上线步骤与监控指标,帮助你从方案评审到实施落地一条龙完成,显著缩短响应时间、稳定高峰期性能,并让优化成效可度量、可复盘、可迭代。

适用用户

数据库管理员(DBA)

在新老库上线或性能回归时,快速盘点关键表与慢查询,一键生成索引组合与创建语句,评估读写权衡并制定清理计划,稳定峰值时延。

后端开发工程师

为新功能设计查询方案时,借助模板选择合适索引与字段顺序,提前规避全表扫描;在代码评审前输出可读的方案说明,缩短联调与回归时间。

数据分析/BI工程师

针对报表与聚合查询,生成覆盖索引与排序策略,显著缩短跑批与仪表盘加载时间,保障日常SLA与临时报表响应。

特征总结

一键解析表结构与查询模式,自动生成可落地的索引优化方案与说明。
针对交易、高并发、报表等场景,智能匹配索引类型与字段顺序,减少慢查询。
自动评估查询加速收益与写入成本,给出权衡建议,避免因过度索引拖慢更新。
输出具体创建语句与实施步骤,含监控指标与验证方法,确保方案快速上线可追踪。
自动识别冗余或无效索引,给出清理建议,释放存储空间并降低维护复杂度。
支持覆盖索引与组合策略,按业务查询优先级排序推荐,聚焦最有价值的优化点。
根据数据分布与选择性,自动调整索引粒度与列顺序,兼顾读写与磁盘占用。
适配主流数据库与存储引擎实践,一键切换输出语言与写作风格,便于跨团队协作。
内置审查规则,拒绝未经验证的索引建议,保障稳定性与合规性与可预期性能。
面向持续优化,提供重建频率、碎片监控与阈值建议,长期保持查询体验稳定。

如何使用购买的提示词模板

1. 直接在外部 Chat 应用中使用

将模板生成的提示词复制粘贴到您常用的 Chat 应用(如 ChatGPT、Claude 等),即可直接对话使用,无需额外开发。适合个人快速体验和轻量使用场景。

2. 发布为 API 接口调用

把提示词模板转化为 API,您的程序可任意修改模板参数,通过接口直接调用,轻松实现自动化与批量处理。适合开发者集成与业务系统嵌入。

3. 在 MCP Client 中配置使用

在 MCP client 中配置对应的 server 地址,让您的 AI 应用自动调用提示词模板。适合高级用户和团队协作,让提示词在不同 AI 工具间无缝衔接。

AI 提示词价格
¥20.00元
先用后买,用好了再付款,超安全!

您购买后可以获得什么

获得完整提示词模板
- 共 561 tokens
- 3 个可调节参数
{ 表结构详情 } { 输出语言 } { 技术写作风格 }
获得社区贡献内容的使用权
- 精选社区优质案例,助您快速上手提示词
使用提示词兑换券,低至 ¥ 9.9
了解兑换券 →
限时半价

不要错过!

半价获取高级提示词-优惠即将到期

17
:
23
小时
:
59
分钟
:
59