MST

星途 面试题库

面试题:MySQL查询性能剖析在高并发场景下的应用

在一个高并发的电商系统中,数据库使用MySQL。有一个需求是实时查询热门商品的销售数据,包括商品ID、商品名称、销售数量,并且销售数量要按照从高到低排序。已知商品表(products)包含商品ID、商品名称字段,订单表(orders)包含订单ID、商品ID、购买数量字段,订单表数据量非常大。请描述你如何设计查询,以及如何利用MySQL的查询性能剖析工具(如SHOW STATUS、SHOW PROFILE等)来确保在高并发场景下该查询的性能优化,同时要考虑到数据一致性问题。
39.1万 热度难度
数据库MySQL

知识考点

AI 面试

面试题答案

一键面试

查询设计

  1. 使用临时表:由于订单表数据量巨大,直接关联查询性能较差。可以先通过子查询统计每个商品的销售数量,将结果存储在临时表中,再与商品表进行关联查询。
-- 创建临时表统计每个商品的销售数量
CREATE TEMPORARY TABLE temp_sales AS
SELECT product_id, SUM(purchase_quantity) AS total_sales
FROM orders
GROUP BY product_id;

-- 从临时表和商品表中查询热门商品销售数据并排序
SELECT p.product_id, p.product_name, ts.total_sales
FROM products p
JOIN temp_sales ts ON p.product_id = ts.product_id
ORDER BY ts.total_sales DESC;
  1. 索引优化
    • orders表的product_idpurchase_quantity字段上创建复合索引,以加速子查询中的分组和求和操作。
    CREATE INDEX idx_product_purchase ON orders (product_id, purchase_quantity);
    
    • products表的product_id字段上创建索引,以加速连接操作。
    CREATE INDEX idx_product_id ON products (product_id);
    

性能剖析与优化

  1. 使用SHOW STATUS
    • 查询缓存命中率:通过SHOW STATUS LIKE 'Qcache%';查看查询缓存的相关状态,如Qcache_hits(缓存命中次数)和Qcache_inserts(缓存插入次数)。如果缓存命中率较低,可能需要调整查询缓存的配置或考虑其他缓存策略。
    • InnoDB相关状态:使用SHOW STATUS LIKE 'InnoDB%';查看InnoDB引擎的状态,如InnoDB_buffer_pool_reads(InnoDB缓冲池读次数)和InnoDB_buffer_pool_read_requests(InnoDB缓冲池读请求次数)。如果读次数过高,可能需要增加缓冲池大小。
  2. 使用SHOW PROFILE
    • 开启查询剖析功能:SET profiling = 1;
    • 执行查询:SELECT p.product_id, p.product_name, ts.total_sales FROM products p JOIN temp_sales ts ON p.product_id = ts.product_id ORDER BY ts.total_sales DESC;
    • 查看剖析结果:SHOW PROFILES;找到对应查询的query_id,然后SHOW PROFILE FOR QUERY [query_id];查看详细的性能信息,如每个操作的执行时间、等待事件等,根据这些信息针对性地优化查询。

数据一致性问题

  1. 事务隔离级别:选择合适的事务隔离级别,如READ - COMMITTED,在保证数据一致性的前提下尽量减少锁的持有时间。可以通过SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;设置。
  2. 乐观锁与悲观锁
    • 悲观锁:如果对数据一致性要求极高,在查询热门商品销售数据时可以使用悲观锁,如SELECT p.product_id, p.product_name, ts.total_sales FROM products p JOIN temp_sales ts ON p.product_id = ts.product_id ORDER BY ts.total_sales DESC FOR UPDATE;,但这种方式会增加锁的竞争,影响并发性能。
    • 乐观锁:在更新销售数据时,可以使用乐观锁机制。例如,在订单表中增加一个版本号字段version,每次更新销售数据时,先读取当前版本号,更新时带上版本号并检查版本号是否匹配,如果匹配则更新成功并递增版本号,否则重试。
-- 假设orders表有version字段
START TRANSACTION;
-- 读取订单数据及版本号
SELECT purchase_quantity, version FROM orders WHERE order_id = [order_id] FOR UPDATE;
-- 更新销售数据,假设新的购买数量为new_purchase_quantity
UPDATE orders SET purchase_quantity = purchase_quantity + new_purchase_quantity, version = version + 1 WHERE order_id = [order_id] AND version = [old_version];
COMMIT;