最优化实例(SQL优化实战100案例)

最优化实例(SQL优化实战100案例)

adminqwq 2026-02-19 社会资讯 7 次浏览 0个评论
SQL优化实战100案例

目录

1.基础优化策略

2.索引优化案例

3.查询重写案例

4.JOIN优化案例

5.子查询优化案例

6.分页优化案例

7.统计聚合优化

8.大数据量处理

9.数据库设计优化

10.实战综合案例

一、基础优化策略案例1:SELECT * 问题

-- 原SQLSELECT * FROM orders WHERE user_id = 1000;

-- 优化后SELECT order_id, order_date, amount FROM orders WHERE user_id = 1000;

案例2:LIMIT滥用

-- 原SQLSELECT * FROM products LIMIT 1000;

-- 优化后SELECT product_id, name, price FROM products WHERE is_active = 1 LIMIT 100;

案例3:避免在WHERE中使用函数

-- 原SQLSELECT * FROM orders WHERE DATE(order_date) = '2024-01-01';

-- 优化后SELECT * FROM orders WHERE order_date >= '2024-01-01'

AND order_date < '2024-01-02';

二、索引优化案例案例4:最左前缀原则

-- 表结构CREATE TABLE orders (

order_id INT PRIMARY KEY,

user_id INT,

status VARCHAR(20),

order_date DATE,

INDEX idx_user_status_date (user_id, status, order_date));

-- 原SQL:无法使用完整索引SELECT * FROM orders WHERE status = 'shipped';

-- 优化SQL1:使用索引最左列SELECT * FROM orders WHERE user_id = 1000 AND status = 'shipped';

-- 优化SQL2:调整索引顺序CREATE INDEX idx_status_user_date ON orders(status, user_id, order_date);

案例5:覆盖索引优化

-- 原SQL:需要回表SELECT order_id, user_id, order_date FROM orders WHERE status = 'pending' ORDER BY order_date DESC;

-- 优化:创建覆盖索引CREATE INDEX idx_status_date_covering ON orders(status, order_date, user_id, order_id);

案例6:索引列顺序优化

-- 低效索引CREATE INDEX idx_date_user ON orders(order_date, user_id);

-- 高效索引(基于查询模式)CREATE INDEX idx_user_date ON orders(user_id, order_date);

-- 查询优化SELECT * FROM orders WHERE user_id = 1000

AND order_date BETWEEN '2024-01-01' AND '2024-12-31';

案例7:索引选择性优化

-- 低选择性索引(只有3种状态)CREATE INDEX idx_status ON orders(status);

-- 高选择性索引组合CREATE INDEX idx_status_date ON orders(status, order_date);

-- 更优:选择性更高的列在前CREATE INDEX idx_date_status ON orders(order_date, status);

案例8:函数索引(MySQL 8.0+)

-- 原SQL:无法使用索引SELECT * FROM users WHERE LOWER(email) = 'user@example.com';

-- 创建函数索引CREATE INDEX idx_email_lower ON users((LOWER(email)));

-- 优化后查询SELECT * FROM users WHERE LOWER(email) = 'user@example.com';

案例9:前缀索引优化

-- 大文本字段索引优化CREATE TABLE logs (

id INT PRIMARY KEY,

url VARCHAR(500),

INDEX idx_url (url(100)) -- 前100字符索引);

-- 计算合适的前缀长度SELECT

COUNT(DISTINCT LEFT(url, 50)) / COUNT(*) as selectivity_50,

COUNT(DISTINCT LEFT(url, 100)) / COUNT(*) as selectivity_100,

COUNT(DISTINCT LEFT(url, 200)) / COUNT(*) as selectivity_200FROM logs;

案例10:删除冗余索引

-- 冗余索引检测SHOW INDEX FROM orders;

-- 删除冗余索引DROP INDEX idx_user_id ON orders; -- 如果已有复合索引(user_id, status)

-- 使用复合索引代替多个单列索引CREATE INDEX idx_user_status_date ON orders(user_id, status, order_date);

三、查询重写案例案例11:OR优化

-- 原SQL:可能导致全表扫描SELECT * FROM products WHERE category_id = 1

OR category_id = 2

OR price > 100;

-- 优化1:使用UNION ALLSELECT * FROM products WHERE category_id = 1UNION ALLSELECT * FROM products WHERE category_id = 2UNION ALLSELECT * FROM products WHERE price > 100

AND category_id NOT IN (1, 2);

-- 优化2:使用INSELECT * FROM products WHERE category_id IN (1, 2)

OR price > 100;

案例12:IN vs EXISTS

-- 小表驱动大表用EXISTSSELECT * FROM orders oWHERE EXISTS (

SELECT 1 FROM users u

WHERE u.user_id = o.user_id

AND u.is_vip = 1);

-- 大表驱动小表用INSELECT * FROM orders WHERE user_id IN (

SELECT user_id FROM vip_users);

案例13:DISTINCT优化

-- 原SQL:使用DISTINCTSELECT DISTINCT u.user_id, u.nameFROM users uJOIN orders o ON u.user_id = o.user_id;

-- 优化1:使用EXISTSSELECT u.user_id, u.nameFROM users uWHERE EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.user_id);

-- 优化2:使用GROUP BYSELECT u.user_id, u.nameFROM users uJOIN orders o ON u.user_id = o.user_idGROUP BY u.user_id, u.name;

案例14:LIKE优化

-- 原SQL:前导通配符无法使用索引SELECT * FROM products WHERE name LIKE '%apple%';

-- 优化1:后通配符可以使用索引SELECT * FROM products WHERE name LIKE 'apple%';

-- 优化2:全文索引CREATE FULLTEXT INDEX idx_name_ft ON products(name);SELECT * FROM products WHERE MATCH(name) AGAINST('apple' IN NATURAL LANGUAGE MODE);

-- 优化3:使用覆盖索引CREATE INDEX idx_name_covering ON products(name, product_id, price);SELECT product_id, price FROM products WHERE name LIKE 'apple%';

四、JOIN优化案例案例15:JOIN顺序优化

-- 原SQL:大表在前SELECT * FROM large_table lJOIN small_table s ON l.small_id = s.id;

-- 优化后:小表在前SELECT /*+ STRAIGHT_JOIN */ FROM small_table sJOIN large_table l ON s.id = l.small_id;

案例16:避免笛卡尔积

-- 原SQL:隐式笛卡尔积SELECT * FROM table1, table2;

-- 优化后:显式JOINSELECT * FROM table1 JOIN table2 ON table1.id = table2.table1_id;

案例17:JOIN条件优化

-- 原SQL:JOIN条件包含计算SELECT * FROM orders oJOIN products p ON o.product_id = p.id

AND DATE(o.order_date) = DATE(p.created_at);

-- 优化后:避免函数计算SELECT * FROM orders oJOIN products p ON o.product_id = p.id

AND o.order_date >= DATE(p.created_at)

AND o.order_date < DATE(p.created_at) + INTERVAL 1 DAY;

案例18:LEFT JOIN优化

-- 原SQL:在JOIN条件外过滤SELECT o.*, u.nameFROM orders oLEFT JOIN users u ON o.user_id = u.user_idWHERE u.is_active = 1; -- 这会将LEFT JOIN转为INNER JOIN

-- 优化后:过滤条件放在ON中SELECT o.*, u.nameFROM orders oLEFT JOIN users u ON o.user_id = u.user_id AND u.is_active = 1;

案例19:多重JOIN优化

-- 原SQL:复杂多重JOINSELECT *FROM orders oJOIN order_items oi ON o.order_id = oi.order_idJOIN products p ON oi.product_id = p.idJOIN categories c ON p.category_id = c.idJOIN users u ON o.user_id = u.user_id;

-- 优化:减少JOIN数量WITH order_details AS (

SELECT o.*, oi.product_id

FROM orders o

JOIN order_items oi ON o.order_id = oi.order_id)SELECT od.*, p.name, u.usernameFROM order_details odJOIN products p ON od.product_id = p.idJOIN users u ON od.user_id = u.user_id;

五、子查询优化案例案例20:相关子查询优化

-- 原SQL:相关子查询SELECT u.name,

(SELECT COUNT(*) FROM orders o WHERE o.user_id = u.user_id) as order_countFROM users u;

-- 优化1:使用LEFT JOINSELECT u.name, COUNT(o.order_id) as order_countFROM users uLEFT JOIN orders o ON u.user_id = o.user_idGROUP BY u.user_id, u.name;

-- 优化2:使用派生表SELECT u.name, IFNULL(t.order_count, 0) as order_countFROM users uLEFT JOIN (

SELECT user_id, COUNT(*) as order_count

FROM orders

GROUP BY user_id) t ON u.user_id = t.user_id;

案例21:IN子查询优化

-- 原SQL:IN子查询SELECT * FROM productsWHERE category_id IN (

SELECT category_id FROM categories WHERE is_active = 1);

-- 优化1:使用JOINSELECT p.*FROM products pJOIN categories c ON p.category_id = c.category_idWHERE c.is_active = 1;

-- 优化2:使用EXISTSSELECT * FROM products pWHERE EXISTS (

SELECT 1 FROM categories c

WHERE c.category_id = p.category_id

AND c.is_active = 1);

案例22:多层子查询优化

-- 原SQL:多层嵌套SELECT * FROM ordersWHERE user_id IN (

SELECT user_id FROM users

WHERE city_id IN (

SELECT city_id FROM cities WHERE country = 'China'

));

-- 优化:扁平化查询SELECT o.*FROM orders oJOIN users u ON o.user_id = u.user_idJOIN cities c ON u.city_id = c.city_idWHERE c.country = 'China';

六、分页优化案例案例23:深度分页优化

-- 原SQL:LIMIT深度分页SELECT * FROM orders ORDER BY order_date DESC LIMIT 1000000, 20; -- 非常慢!

-- 优化1:使用覆盖索引+JOINSELECT o.*FROM orders oJOIN (

SELECT order_id

FROM orders

ORDER BY order_date DESC

LIMIT 1000000, 20) t ON o.order_id = t.order_id;

-- 优化2:使用游标分页SELECT * FROM orders WHERE order_date < '2024-01-01' -- 上次最后一条的时间ORDER BY order_date DESC LIMIT 20;

案例24:分页+JOIN优化

-- 原SQL:分页包含JOINSELECT o.*, u.nameFROM orders oJOIN users u ON o.user_id = u.user_idORDER BY o.order_date DESCLIMIT 0, 20;

-- 优化:先分页再JOINSELECT o.*, u.nameFROM (

SELECT * FROM orders

ORDER BY order_date DESC

LIMIT 0, 20) oJOIN users u ON o.user_id = u.user_id;

七、统计聚合优化案例25:COUNT优化

-- 原SQL:COUNT(*)SELECT COUNT(*) FROM orders WHERE status = 'pending';

-- 优化1:使用覆盖索引CREATE INDEX idx_status ON orders(status);

-- 优化2:定期统计表CREATE TABLE order_stats (

stat_date DATE PRIMARY KEY,

pending_count INT,

shipped_count INT);

案例26:GROUP BY优化

-- 原SQL:GROUP BY多个字段SELECT category_id, status, COUNT(*)FROM ordersGROUP BY category_id, status;

-- 优化:使用复合索引CREATE INDEX idx_category_status ON orders(category_id, status);

-- 使用ROLLUPSELECT category_id, status, COUNT(*)FROM ordersGROUP BY category_id, status WITH ROLLUP;

案例27:窗口函数优化

-- 原SQL:复杂窗口函数SELECT

user_id,

order_date,

amount,

SUM(amount) OVER (PARTITION BY user_id ORDER BY order_date) as running_total,

ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY order_date DESC) as rnFROM orders;

-- 优化:减少窗口函数使用WITH ranked_orders AS (

SELECT *,

ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY order_date DESC) as rn

FROM orders)SELECT user_id, order_date, amountFROM ranked_ordersWHERE rn <= 10; -- 每个用户最近10个订单

八、大数据量处理案例28:批量插入优化

-- 原SQL:单条插入INSERT INTO logs (message, created_at) VALUES ('log1', NOW());INSERT INTO logs (message, created_at) VALUES ('log2', NOW());

-- 优化:批量插入INSERT INTO logs (message, created_at) VALUES ('log1', NOW()),('log2', NOW()),('log3', NOW());

-- 大批量数据优化LOAD DATA INFILE '/path/to/data.csv'INTO TABLE logsFIELDS TERMINATED BY ','LINES TERMINATED BY '\n';

案例29:分区表优化

-- 创建分区表CREATE TABLE orders_partitioned (

order_id INT PRIMARY KEY,

user_id INT,

order_date DATE,

amount DECIMAL(10,2))PARTITION BY RANGE (YEAR(order_date)) (

PARTITION p2022 VALUES LESS THAN (2023),

PARTITION p2023 VALUES LESS THAN (2024),

PARTITION p2024 VALUES LESS THAN (2025));

-- 查询指定分区SELECT * FROM orders_partitioned WHERE order_date >= '2024-01-01'PARTITION (p2024);

案例30:归档历史数据

-- 1. 创建归档表CREATE TABLE orders_archive LIKE orders;

-- 2. 迁移历史数据INSERT INTO orders_archiveSELECT * FROM orders WHERE order_date < '2023-01-01';

-- 3. 删除原表数据DELETE FROM orders WHERE order_date < '2023-01-01';

-- 4. 定期优化表OPTIMIZE TABLE orders;

九、数据库设计优化案例31:范式化vs反范式化

-- 范式化设计(3NF)CREATE TABLE orders (

order_id INT PRIMARY KEY,

user_id INT,

order_date DATE);

CREATE TABLE order_items (

item_id INT PRIMARY KEY,

order_id INT,

product_id INT,

quantity INT,

price DECIMAL(10,2));

-- 反范式化设计(查询优化)CREATE TABLE orders_denormalized (

order_id INT PRIMARY KEY,

user_id INT,

user_name VARCHAR(100), -- 冗余用户信息

order_date DATE,

total_amount DECIMAL(10,2), -- 预计算总和

item_count INT -- 预计算计数);

案例32:枚举类型优化

-- 原设计:VARCHAR存储状态CREATE TABLE orders (

status VARCHAR(20) -- 'pending', 'shipped', 'delivered');

-- 优化1:使用ENUMCREATE TABLE orders (

status ENUM('pending', 'shipped', 'delivered', 'cancelled'));

-- 优化2:使用TINYINTCREATE TABLE orders (

status TINYINT, -- 1:pending, 2:shipped, 3:delivered, 4:cancelled

INDEX idx_status (status));

-- 使用JOIN表维护状态映射CREATE TABLE order_statuses (

status_id TINYINT PRIMARY KEY,

status_name VARCHAR(20));

案例33:JSON字段优化

-- 原设计:JSON存储动态字段CREATE TABLE products (

product_id INT PRIMARY KEY,

attributes JSON -- 包含各种动态属性);

-- 优化:提取常用字段CREATE TABLE products (

product_id INT PRIMARY KEY,

price DECIMAL(10,2),

stock INT,

attributes JSON, -- 存储不常用字段

INDEX idx_price (price),

INDEX idx_stock (stock));

-- 使用虚拟列+索引ALTER TABLE products ADD COLUMN weight DECIMAL(10,2)

GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(attributes, '$.weight'))) STORED,ADD INDEX idx_weight (weight);

案例34:时间字段优化

-- 原设计:字符串存储时间CREATE TABLE logs (

log_time VARCHAR(19) -- '2024-01-01 12:00:00');

-- 优化1:使用TIMESTAMPCREATE TABLE logs (

log_time TIMESTAMP,

INDEX idx_log_time (log_time));

-- 优化2:分区+索引CREATE TABLE logs_partitioned (

log_time TIMESTAMP,

message TEXT)PARTITION BY RANGE (UNIX_TIMESTAMP(log_time)) (

PARTITION p202401 VALUES LESS THAN (UNIX_TIMESTAMP('2024-02-01')),

PARTITION p202402 VALUES LESS THAN (UNIX_TIMESTAMP('2024-03-01')));

-- 使用DATE类型单独存储日期ALTER TABLE logs ADD COLUMN log_date DATE

GENERATED ALWAYS AS (DATE(log_time)) STORED,ADD INDEX idx_log_date (log_date);

十、实战综合案例案例35:电商订单查询优化

-- 原复杂查询SELECT

u.user_id,

u.name,

COUNT(DISTINCT o.order_id) as order_count,

SUM(oi.quantity * oi.price) as total_spent,

MAX(o.order_date) as last_order_dateFROM users uLEFT JOIN orders o ON u.user_id = o.user_idLEFT JOIN order_items oi ON o.order_id = oi.order_idWHERE u.register_date >= '2023-01-01'

AND u.is_active = 1

AND o.status IN ('completed', 'shipped')GROUP BY u.user_id, u.nameHAVING total_spent > 1000ORDER BY total_spent DESCLIMIT 100;

-- 优化方案-- 1. 创建索引CREATE INDEX idx_users_active_date ON users(is_active, register_date);CREATE INDEX idx_orders_user_status ON orders(user_id, status);CREATE INDEX idx_order_items_order ON order_items(order_id);

-- 2. 使用派生表分步查询WITH user_orders AS (

SELECT

o.user_id,

o.order_id,

o.order_date

FROM orders o

WHERE o.status IN ('completed', 'shipped')),

order_totals AS (

SELECT

order_id,

SUM(quantity * price) as order_amount

FROM order_items

GROUP BY order_id),

user_summary AS (

SELECT

u.user_id,

u.name,

COUNT(DISTINCT uo.order_id) as order_count,

SUM(ot.order_amount) as total_spent,

MAX(uo.order_date) as last_order_date

FROM users u

JOIN user_orders uo ON u.user_id = uo.user_id

JOIN order_totals ot ON uo.order_id = ot.order_id

WHERE u.register_date >= '2023-01-01'

AND u.is_active = 1

GROUP BY u.user_id, u.name

HAVING SUM(ot.order_amount) > 1000)SELECT * FROM user_summaryORDER BY total_spent DESCLIMIT 100;

案例36:实时数据分析优化

-- 原实时聚合查询SELECT

DATE(created_at) as date,

product_id,

COUNT(*) as view_count,

COUNT(DISTINCT user_id) as unique_usersFROM product_viewsWHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)GROUP BY DATE(created_at), product_idORDER BY date DESC, view_count DESC;

-- 优化:使用物化视图/汇总表CREATE TABLE product_view_summary (

summary_date DATE,

product_id INT,

view_count INT DEFAULT 0,

unique_users INT DEFAULT 0,

PRIMARY KEY (summary_date, product_id),

INDEX idx_date_count (summary_date, view_count DESC)) ENGINE=InnoDB;

-- 每小时更新汇总表INSERT INTO product_view_summary (summary_date, product_id, view_count, unique_users)SELECT

DATE(created_at) as summary_date,

product_id,

COUNT(*) as view_count,

COUNT(DISTINCT user_id) as unique_usersFROM product_viewsWHERE created_at >= DATE_SUB(NOW(), INTERVAL 1 HOUR)GROUP BY DATE(created_at), product_idON DUPLICATE KEY UPDATE

view_count = view_count + VALUES(view_count),

unique_users = unique_users + VALUES(unique_users);

-- 查询优化后SELECT

summary_date as date,

product_id,

view_count,

unique_usersFROM product_view_summaryWHERE summary_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)ORDER BY summary_date DESC, view_count DESC;

案例37:消息系统查询优化

-- 原消息查询SELECT

m.*,

u1.username as sender_name,

u2.username as receiver_nameFROM messages mJOIN users u1 ON m.sender_id = u1.user_idJOIN users u2 ON m.receiver_id = u2.user_idWHERE (m.sender_id = 1000 OR m.receiver_id = 1000)

AND m.is_deleted = 0ORDER BY m.created_at DESCLIMIT 0, 50;

-- 优化方案-- 1. 创建复合索引CREATE INDEX idx_user_conversation ON messages(

GREATEST(sender_id, receiver_id),

LEAST(sender_id, receiver_id),

created_at DESC);

-- 2. 使用UNION优化OR条件(SELECT m.*

FROM messages m

WHERE m.sender_id = 1000 AND m.is_deleted = 0

ORDER BY m.created_at DESC

LIMIT 50)UNION ALL(SELECT m.*

FROM messages m

WHERE m.receiver_id = 1000 AND m.is_deleted = 0

ORDER BY m.created_at DESC

LIMIT 50)ORDER BY created_at DESCLIMIT 50;

-- 3. 最终优化查询SELECT

m.*,

u1.username as sender_name,

u2.username as receiver_nameFROM (

SELECT message_id

FROM messages

WHERE (sender_id = 1000 OR receiver_id = 1000)

AND is_deleted = 0

ORDER BY created_at DESC

LIMIT 0, 50) recent_idsJOIN messages m ON recent_ids.message_id = m.message_idJOIN users u1 ON m.sender_id = u1.user_idJOIN users u2 ON m.receiver_id = u2.user_idORDER BY m.created_at DESC;

案例38:社交网络好友关系查询

-- 原查询:查找共同好友SELECT

u.user_id,

u.usernameFROM users uJOIN friendships f1 ON u.user_id = f1.friend_idJOIN friendships f2 ON u.user_id = f2.friend_idWHERE f1.user_id = 1000 -- 用户A

AND f2.user_id = 2000 -- 用户B

AND f1.status = 'accepted'

AND f2.status = 'accepted';

-- 优化方案-- 1. 创建索引CREATE INDEX idx_friendships_user_friend ON friendships(user_id, friend_id, status);

-- 2. 使用INTERSECT替代(如果支持)SELECT friend_idFROM friendshipsWHERE user_id = 1000 AND status = 'accepted'INTERSECTSELECT friend_idFROM friendshipsWHERE user_id = 2000 AND status = 'accepted';

-- 3. MySQL中使用JOIN优化SELECT f1.friend_idFROM friendships f1JOIN friendships f2 ON f1.friend_id = f2.friend_idWHERE f1.user_id = 1000

AND f2.user_id = 2000

AND f1.status = 'accepted'

AND f2.status = 'accepted';

-- 4. 使用EXISTS优化SELECT u.user_id, u.usernameFROM users uWHERE EXISTS (

SELECT 1 FROM friendships f1

WHERE f1.user_id = 1000

AND f1.friend_id = u.user_id

AND f1.status = 'accepted') AND EXISTS (

SELECT 1 FROM friendships f2

WHERE f2.user_id = 2000

AND f2.friend_id = u.user_id

AND f2.status = 'accepted');

案例39:地理空间查询优化

-- 原查询:查找附近地点SELECT

place_id,

name,

address,

(6371 * ACOS(

COS(RADIANS(31.2304)) * COS(RADIANS(latitude)) *

COS(RADIANS(longitude) - RADIANS(121.4737)) +

SIN(RADIANS(31.2304)) * SIN(RADIANS(latitude))

)) as distance_kmFROM placesWHERE category = 'restaurant'HAVING distance_km <= 5ORDER BY distance_kmLIMIT 20;

-- 优化:使用空间索引-- 1. 添加空间数据ALTER TABLE placesADD COLUMN location POINT NOT NULL,ADD SPATIAL INDEX idx_location (location);

UPDATE places SET location = POINT(longitude, latitude);

-- 2. 使用MBRContains优化SELECT

place_id,

name,

address,

ST_Distance_Sphere(

location,

ST_GeomFromText('POINT(121.4737 31.2304)')

) / 1000 as distance_kmFROM placesWHERE category = 'restaurant'

AND MBRContains(

ST_GeomFromText('Polygon((

121.4737 - 0.045 31.2304 - 0.045,

121.4737 + 0.045 31.2304 - 0.045,

121.4737 + 0.045 31.2304 + 0.045,

121.4737 - 0.045 31.2304 + 0.045,

121.4737 - 0.045 31.2304 - 0.045

))'),

location

)HAVING distance_km <= 5ORDER BY distance_kmLIMIT 20;

案例40:全文搜索优化

-- 原LIKE搜索SELECT * FROM articlesWHERE title LIKE '%数据库优化%'

OR content LIKE '%数据库优化%';

-- 优化1:使用全文索引CREATE FULLTEXT INDEX idx_article_search ON articles(title, content);

SELECT

*,

MATCH(title, content) AGAINST('数据库优化') as relevanceFROM articlesWHERE MATCH(title, content) AGAINST('数据库优化' IN NATURAL LANGUAGE MODE)ORDER BY relevance DESC;

-- 优化2:使用布尔模式SELECT * FROM articlesWHERE MATCH(title, content) AGAINST('+数据库 +优化' IN BOOLEAN MODE);

-- 优化3:使用扩展查询SELECT * FROM articlesWHERE MATCH(title, content) AGAINST('数据库优化' WITH QUERY EXPANSION);

-- 优化4:结合LIKE和全文索引SELECT * FROM articlesWHERE MATCH(title, content) AGAINST('数据库*' IN BOOLEAN MODE)

AND (title LIKE '%优化%' OR content LIKE '%优化%');

更多案例速览(41-100)案例41-50:性能监控与调优

-- 41. 慢查询日志分析SET GLOBAL slow_query_log = ON;SET GLOBAL long_query_time = 2;

-- 42. 查看执行计划EXPLAIN FORMAT=JSONSELECT * FROM orders WHERE user_id = 1000;

-- 43. 使用索引提示SELECT /*+ INDEX(orders idx_user_id) */ *FROM orders WHERE user_id = 1000;

-- 44. 强制连接顺序SELECT /*+ STRAIGHT_JOIN */ *FROM small_table sJOIN large_table l ON s.id = l.small_id;

-- 45. 优化器提示SELECT /*+ MAX_EXECUTION_TIME(1000) */ *FROM large_table;

-- 46. 查询缓存优化SELECT SQL_NO_CACHE * FROM orders;

-- 47. 临时表优化CREATE TEMPORARY TABLE temp_ordersENGINE=MemorySELECT * FROM orders WHERE order_date > '2024-01-01';

-- 48. 批量更新优化UPDATE large_tableSET status = 'inactive'WHERE last_active < DATE_SUB(NOW(), INTERVAL 1 YEAR)LIMIT 1000; -- 分批更新

-- 49. 死锁避免START TRANSACTION;SELECT * FROM accounts WHERE id = 1 FOR UPDATE;-- 按相同顺序访问表避免死锁

-- 50. 连接池优化SHOW STATUS LIKE 'Threads_connected';SET GLOBAL max_connections = 500;

案例51-60:数据类型优化

-- 51. INT类型选择TINYINT -- -128到127SMALLINT -- -32768到32767MEDIUMINT -- -8388608到8388607INT -- -2147483648到2147483647BIGINT -- 更大范围

-- 52. 字符串类型优化CHAR(10) -- 固定长度VARCHAR(10) -- 可变长度TEXT -- 大文本BLOB -- 二进制

-- 53. 时间类型选择TIMESTAMP -- 4字节,时区相关DATETIME -- 8字节,时区无关DATE -- 3字节,只存日期TIME -- 3字节,只存时间

-- 54. 小数类型优化DECIMAL(10,2) -- 精确小数FLOAT -- 4字节,近似值DOUBLE -- 8字节,近似值

-- 55. 枚举优化ENUM('small','medium','large') -- 存储为整数

案例61-70:事务优化

-- 61. 事务隔离级别SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

-- 62. 避免长事务SET innodb_lock_wait_timeout = 50;SET innodb_rollback_on_timeout = ON;

-- 63. 批量提交START TRANSACTION;-- 批量操作COMMIT;

-- 64. 锁优化SELECT * FROM table WHERE id = 1 LOCK IN SHARE MODE;SELECT * FROM table WHERE id = 1 FOR UPDATE;

-- 65. 避免间隙锁SELECT * FROM table WHERE index_column = 100

AND unique_column = 200 FOR UPDATE;

案例71-80:复制与高可用优化

-- 71. 主从复制优化SHOW SLAVE STATUS\G

-- 72. 读写分离-- 写操作INSERT INTO orders ...; -- 主库

-- 读操作SELECT * FROM orders ...; -- 从库

-- 73. 分库分表策略-- 按用户ID分片

shard_id = user_id % 64

-- 74. 全局唯一IDCREATE TABLE sequence (

id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY) ENGINE=MyISAM;

-- 75. 数据一致性检查

CHECKSUM TABLE orders;

案例81-90:备份与恢复优化

-- 81. 在线备份

mysqldump --single-transaction --routines dbname > backup.-- 82. 增量备份

mysqlbinlog mysql-bin.000001 > binlog.-- 83. 快速恢复

mysql -e "SET foreign_key_checks=0; source backup.sql"

-- 84. 分区表备份ALTER TABLE orders EXCHANGE PARTITION p2024 WITH TABLE orders_backup;

-- 85. 并行备份

mydumper -t 4 -B dbname -o /backup/

案例91-100:高级优化技巧

-- 91. 使用窗口函数优化SELECT *,

LAG(amount) OVER (PARTITION BY user_id ORDER BY order_date) as prev_amountFROM orders;

-- 92. CTE递归查询WITH RECURSIVE cte AS (

SELECT 1 as n

UNION ALL

SELECT n + 1 FROM cte WHERE n < 100)SELECT * FROM cte;

-- 93. JSON函数优化SELECT

JSON_EXTRACT(data, '$.price') as price,

JSON_CONTAINS_PATH(data, 'one', '$.discount') as has_discountFROM products;

-- 94. 生成列优化ALTER TABLE ordersADD COLUMN order_year YEAR

GENERATED ALWAYS AS (YEAR(order_date)) STORED;

-- 95. 使用GIS函数SELECT

ST_AsText(location),

ST_Distance_Sphere(location, @user_location) as distanceFROM places;

-- 96. 优化UNION查询(SELECT * FROM table1 WHERE ... LIMIT 10)UNION ALL(SELECT * FROM table2 WHERE ... LIMIT 10)LIMIT 10;

-- 97. 使用变量优化SET @row_number = 0;SELECT

(@row_number:=@row_number + 1) AS row_num,

user_id, nameFROM users;

-- 98. 避免触发器性能问题-- 使用应用程序逻辑替代触发器

-- 99. 存储过程优化

CREATE PROCEDURE process_orders()BEGIN

DECLARE done INT DEFAULT FALSE;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

-- 批量处理逻辑END;

-- 100. 最终建议/*

1. 永远先看执行计划

2. 索引不是越多越好

3. 避免在数据库层做复杂计算

4. 定期分析表和索引

5. 监控慢查询日志

6. 合理使用缓存

7. 考虑数据归档

8. 测试、测试、再测试

*/

记住:没有最好的优化方案,只有最适合当前场景的方案。在实际应用中,应该根据具体情况进行测试和调整。

#sql# #数据库# #mysq# #mssql# #oracle# #数据库优化# #sql优化#

转载请注明来自海坡下载,本文标题:《最优化实例(SQL优化实战100案例)》

每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,7人围观)参与讨论

还没有评论,来说两句吧...