当前位置: 首页 > news >正文

MySQL查询语句(续)

第4章:MySQL查询语句(续)

4.3 高级功能

MySQL提供了许多高级功能,可以增强数据库的性能、安全性和功能性。本节将详细介绍索引、视图、存储过程、触发器、事务等高级功能。

4.3.1 索引

索引是提高数据库查询性能的关键工具。它们类似于书籍的目录,允许数据库系统快速定位所需的数据,而无需扫描整个表。

索引的类型

MySQL支持多种类型的索引:

  1. B-Tree索引:最常用的索引类型,适用于全键值、键值范围和键前缀查询
  2. 哈希索引:只适用于等值比较,主要用于MEMORY存储引擎
  3. 全文索引:用于全文搜索
  4. 空间索引:用于地理空间数据类型
  5. 前缀索引:对字符串列的前几个字符建立索引
  6. 复合索引:包含多个列的索引
创建索引

可以在创建表时或之后创建索引:

-- 在创建表时创建索引
CREATE TABLE employees (employee_id INT PRIMARY KEY,first_name VARCHAR(50),last_name VARCHAR(50),email VARCHAR(100),hire_date DATE,INDEX idx_name (first_name, last_name),UNIQUE INDEX idx_email (email)
);-- 在现有表上创建索引
CREATE INDEX idx_hire_date ON employees (hire_date);
CREATE UNIQUE INDEX idx_emp_email ON employees (email);-- 使用ALTER TABLE创建索引
ALTER TABLE employees ADD INDEX idx_last_name (last_name);
创建前缀索引

对于长字符串列,可以只索引前几个字符:

CREATE INDEX idx_description ON products (description(50));

这将为description列的前50个字符创建索引。

创建全文索引

全文索引用于全文搜索:

-- 在创建表时创建全文索引
CREATE TABLE articles (id INT PRIMARY KEY,title VARCHAR(200),content TEXT,FULLTEXT INDEX idx_content (content)
);-- 在现有表上创建全文索引
CREATE FULLTEXT INDEX idx_title_content ON articles (title, content);

使用全文索引进行搜索:

-- 自然语言模式
SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('database optimization');-- 布尔模式
SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('+database -optimization' IN BOOLEAN MODE);
查看索引

可以使用以下命令查看表的索引:

-- 方法1
SHOW INDEX FROM employees;-- 方法2
SHOW INDEXES FROM employees;-- 方法3
SHOW KEYS FROM employees;

也可以从INFORMATION_SCHEMA查询索引信息:

SELECT index_name, column_name, non_unique
FROM INFORMATION_SCHEMA.STATISTICS
WHERE table_schema = 'your_database' AND table_name = 'employees';
删除索引

可以使用以下命令删除索引:

-- 方法1
DROP INDEX idx_name ON employees;-- 方法2
ALTER TABLE employees DROP INDEX idx_name;
索引的使用场景

索引适用于以下场景:

  1. WHERE子句中频繁使用的列
  2. JOIN操作中的连接列
  3. ORDER BY或GROUP BY子句中的列
  4. 包含大量唯一值的列
索引的注意事项

虽然索引可以提高查询性能,但也有一些注意事项:

  1. 索引会占用额外的存储空间
  2. 索引会降低写操作(INSERT、UPDATE、DELETE)的性能
  3. 不是所有查询都能使用索引
  4. 过多的索引可能导致优化器选择次优的执行计划
索引最佳实践

以下是一些索引使用的最佳实践:

  1. 为经常在WHERE子句中使用的列创建索引
  2. 为经常在ORDER BY和GROUP BY子句中使用的列创建索引
  3. 为外键列创建索引
  4. 考虑列的基数(唯一值的数量)
  5. 避免对经常更新的列创建过多索引
  6. 使用EXPLAIN分析查询,确保索引被正确使用
  7. 定期检查和优化索引

4.3.2 视图

视图是基于SQL查询的虚拟表,可以像表一样使用。视图不存储数据,而是在查询时动态生成结果。

创建视图

使用CREATE VIEW语句创建视图:

CREATE [OR REPLACE] VIEW view_name AS
SELECT column1, column2, ...
FROM table_name
WHERE condition;

示例:

-- 创建一个简单的视图
CREATE VIEW employee_details AS
SELECT e.employee_id, e.first_name, e.last_name, d.department_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id;-- 创建带列名的视图
CREATE VIEW employee_salaries (id, name, salary, department) AS
SELECT e.employee_id, CONCAT(e.first_name, ' ', e.last_name), e.salary, d.department_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id;
查询视图

视图可以像表一样查询:

SELECT * FROM employee_details;SELECT id, name, department
FROM employee_salaries
WHERE salary > 10000;
修改视图

可以使用ALTER VIEW或CREATE OR REPLACE VIEW修改现有视图:

-- 方法1
ALTER VIEW employee_details AS
SELECT e.employee_id, e.first_name, e.last_name, e.email, d.department_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id;-- 方法2
CREATE OR REPLACE VIEW employee_details AS
SELECT e.employee_id, e.first_name, e.last_name, e.email, d.department_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id;
删除视图

使用DROP VIEW语句删除视图:

DROP VIEW [IF EXISTS] employee_details;
可更新视图

在某些情况下,视图是可更新的,这意味着可以通过视图执行INSERT、UPDATE和DELETE操作:

-- 创建可更新视图
CREATE VIEW active_employees AS
SELECT employee_id, first_name, last_name, email, department_id
FROM employees
WHERE active = 1;-- 通过视图更新数据
UPDATE active_employees
SET department_id = 80
WHERE employee_id = 207;

视图可更新的条件:

  1. 视图必须只基于一个表
  2. 视图不能包含以下元素:
    • 聚合函数(SUM、COUNT等)
    • DISTINCT
    • GROUP BY
    • HAVING
    • UNION
    • 子查询
    • 某些连接操作
  3. 视图必须包含基表的所有NOT NULL且没有默认值的列
带检查选项的视图

可以使用WITH CHECK OPTION子句确保通过视图进行的修改符合视图的定义条件:

CREATE VIEW active_employees AS
SELECT employee_id, first_name, last_name, email, active
FROM employees
WHERE active = 1
WITH CHECK OPTION;

使用此选项后,以下更新将失败,因为它违反了视图的WHERE条件:

UPDATE active_employees
SET active = 0
WHERE employee_id = 207;
视图的优势

视图提供以下优势:

  1. 简化复杂查询:将复杂查询封装为简单视图
  2. 提供数据抽象:隐藏底层表结构的复杂性
  3. 实现行级和列级安全:限制用户只能看到特定的行或列
  4. 提供向后兼容性:当底层表结构变化时,保持应用程序接口稳定

4.3.3 存储过程

存储过程是存储在数据库中的一组SQL语句,可以像函数一样调用。它们可以接受参数、执行操作并返回结果。

创建存储过程

使用CREATE PROCEDURE语句创建存储过程:

DELIMITER //
CREATE PROCEDURE procedure_name(parameter_list)
BEGIN-- SQL语句
END //
DELIMITER ;

参数可以是IN(输入)、OUT(输出)或INOUT(输入输出)类型:

DELIMITER //
CREATE PROCEDURE get_employee_details(IN emp_id INT,OUT emp_name VARCHAR(100),OUT emp_salary DECIMAL(10,2)
)
BEGINSELECT CONCAT(first_name, ' ', last_name), salaryINTO emp_name, emp_salaryFROM employeesWHERE employee_id = emp_id;
END //
DELIMITER ;
调用存储过程

使用CALL语句调用存储过程:

-- 调用不带参数的存储过程
CALL update_statistics();-- 调用带IN参数的存储过程
CALL increase_salaries(60, 10);-- 调用带OUT参数的存储过程
SET @name = '';
SET @salary = 0;
CALL get_employee_details(207, @name, @salary);
SELECT @name, @salary;
存储过程中的变量

可以在存储过程中声明和使用变量:

DELIMITER //
CREATE PROCEDURE calculate_bonus(IN emp_id INT)
BEGINDECLARE salary DECIMAL(10,2);DECLARE years_of_service INT;DECLARE bonus DECIMAL(10,2);-- 获取员工工资和服务年限SELECT salary, FLOOR(DATEDIFF(CURDATE(), hire_date) / 365)INTO salary, years_of_serviceFROM employeesWHERE employee_id = emp_id;-- 计算奖金IF years_of_service < 5 THENSET bonus = salary * 0.05;ELSEIF years_of_service < 10 THENSET bonus = salary * 0.10;ELSESET bonus = salary * 0.15;END IF;-- 返回结果SELECT emp_id, salary, years_of_service, bonus;
END //
DELIMITER ;
存储过程中的流程控制

MySQL存储过程支持多种流程控制语句:

  1. IF语句
IF condition THEN-- statements
ELSEIF another_condition THEN-- statements
ELSE-- statements
END IF;
  1. CASE语句
CASE expressionWHEN value1 THEN-- statementsWHEN value2 THEN-- statementsELSE-- statements
END CASE;-- 或CASEWHEN condition1 THEN-- statementsWHEN condition2 THEN-- statementsELSE-- statements
END CASE;
  1. 循环语句
-- WHILE循环
WHILE condition DO-- statements
END WHILE;-- REPEAT循环(至少执行一次)
REPEAT-- statements
UNTIL condition
END REPEAT;-- LOOP循环(需要显式退出)
loop_label: LOOP-- statementsIF condition THENLEAVE loop_label;END IF;
END LOOP;
存储过程中的错误处理

可以使用DECLARE HANDLER语句处理存储过程中的错误:

DELIMITER //
CREATE PROCEDURE safe_update_salary(IN emp_id INT, IN new_salary DECIMAL(10,2))
BEGIN-- 声明错误处理器DECLARE EXIT HANDLER FOR SQLEXCEPTIONBEGINROLLBACK;SELECT 'Error occurred. Transaction rolled back.' AS message;END;-- 开始事务START TRANSACTION;-- 更新工资UPDATE employeesSET salary = new_salaryWHERE employee_id = emp_id;-- 检查是否找到员工IF ROW_COUNT() = 0 THENSIGNAL SQLSTATE '45000'SET MESSAGE_TEXT = 'Employee not found';END IF;-- 提交事务COMMIT;SELECT 'Salary updated successfully.' AS message;
END //
DELIMITER ;
查看存储过程

可以使用以下命令查看存储过程:

-- 查看所有存储过程
SHOW PROCEDURE STATUS WHERE db = 'your_database';-- 查看特定存储过程的定义
SHOW CREATE PROCEDURE procedure_name;

也可以从INFORMATION_SCHEMA查询存储过程信息:

SELECT routine_name, routine_definition
FROM INFORMATION_SCHEMA.ROUTINES
WHERE routine_schema = 'your_database' AND routine_type = 'PROCEDURE';
修改和删除存储过程

使用ALTER PROCEDURE修改存储过程的特性(但不能修改其内容):

ALTER PROCEDURE procedure_name
COMMENT 'New comment'
SQL SECURITY INVOKER;

要修改存储过程的内容,需要先删除再重新创建。

使用DROP PROCEDURE删除存储过程:

DROP PROCEDURE [IF EXISTS] procedure_name;

4.3.4 函数

MySQL函数类似于存储过程,但它们返回单个值,可以在SQL语句中使用。

创建函数

使用CREATE FUNCTION语句创建函数:

DELIMITER //
CREATE FUNCTION function_name(parameter_list)
RETURNS data_type
[characteristic ...]
BEGIN-- SQL语句RETURN value;
END //
DELIMITER ;

示例:

DELIMITER //
CREATE FUNCTION calculate_age(birth_date DATE)
RETURNS INT
DETERMINISTIC
BEGINRETURN FLOOR(DATEDIFF(CURDATE(), birth_date) / 365);
END //
DELIMITER ;

函数特性(characteristic)包括:

  • DETERMINISTIC:函数对于相同的输入总是返回相同的结果
  • NOT DETERMINISTIC:函数结果可能因外部因素而变化(默认)
  • CONTAINS SQL:函数包含SQL语句,但不读取或修改数据
  • NO SQL:函数不包含SQL语句
  • READS SQL DATA:函数包含读取数据的语句,但不修改数据
  • MODIFIES SQL DATA:函数包含修改数据的语句
使用函数

函数可以在SQL语句中使用:

-- 在SELECT语句中使用
SELECT employee_id, first_name, last_name, birth_date, calculate_age(birth_date) AS age
FROM employees;-- 在WHERE子句中使用
SELECT * FROM employees
WHERE calculate_age(birth_date) > 40;-- 直接调用函数
SELECT calculate_age('1980-01-15');
查看、修改和删除函数

查看函数:

-- 查看所有函数
SHOW FUNCTION STATUS WHERE db = 'your_database';-- 查看特定函数的定义
SHOW CREATE FUNCTION function_name;

修改函数特性(不能修改内容):

ALTER FUNCTION function_name
COMMENT 'New comment'
SQL SECURITY INVOKER;

删除函数:

DROP FUNCTION [IF EXISTS] function_name;

4.3.5 触发器

触发器是在表上执行特定操作(INSERT、UPDATE或DELETE)时自动执行的特殊存储过程。

创建触发器

使用CREATE TRIGGER语句创建触发器:

DELIMITER //
CREATE TRIGGER trigger_name
{BEFORE | AFTER} {INSERT | UPDATE | DELETE} ON table_name
FOR EACH ROW
BEGIN-- SQL语句
END //
DELIMITER ;

示例:

-- 创建BEFORE INSERT触发器
DELIMITER //
CREATE TRIGGER before_employee_insert
BEFORE INSERT ON employees
FOR EACH ROW
BEGIN-- 设置默认值IF NEW.hire_date IS NULL THENSET NEW.hire_date = CURDATE();END IF;
END //
DELIMITER ;-- 创建AFTER UPDATE触发器
DELIMITER //
CREATE TRIGGER after_salary_update
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN-- 记录工资变更IF OLD.salary <> NEW.salary THENINSERT INTO salary_changes (employee_id, old_salary, new_salary, change_date)VALUES (NEW.employee_id, OLD.salary, NEW.salary, NOW());END IF;
END //
DELIMITER ;

在触发器中,可以使用OLD和NEW关键字引用行的旧值和新值:

  • INSERT触发器只能使用NEW
  • DELETE触发器只能使用OLD
  • UPDATE触发器可以使用OLD和NEW
查看触发器

可以使用以下命令查看触发器:

-- 查看所有触发器
SHOW TRIGGERS;-- 查看特定表的触发器
SHOW TRIGGERS WHERE `table` = 'employees';

也可以从INFORMATION_SCHEMA查询触发器信息:

SELECT trigger_name, event_manipulation, action_statement
FROM INFORMATION_SCHEMA.TRIGGERS
WHERE event_object_table = 'employees';
删除触发器

使用DROP TRIGGER语句删除触发器:

DROP TRIGGER [IF EXISTS] trigger_name;
触发器的使用场景

触发器适用于以下场景:

  1. 自动更新时间戳:记录行的最后修改时间
  2. 数据验证:确保插入或更新的数据符合业务规则
  3. 维护冗余数据:自动更新相关表中的冗余数据
  4. 审计日志:记录数据变更
  5. 实现复杂的业务规则:如级联更新或删除
触发器的注意事项

使用触发器时应注意以下几点:

  1. 触发器可能影响性能:特别是在大量数据操作时
  2. 触发器可能导致复杂的调试问题:因为它们是自动执行的
  3. 触发器不应包含复杂的业务逻辑:复杂逻辑应放在应用程序或存储过程中
  4. 触发器不能调用存储过程:但可以调用函数
  5. 触发器不能使用显式或隐式的事务控制语句:如COMMIT或ROLLBACK

4.3.6 事件调度器

MySQL事件调度器允许自动执行计划任务,类似于Unix的cron作业。

启用事件调度器

首先,确保事件调度器已启用:

-- 检查事件调度器状态
SHOW VARIABLES LIKE 'event_scheduler';-- 启用事件调度器
SET GLOBAL event_scheduler = ON;

也可以在MySQL配置文件中启用:

[mysqld]
event_scheduler = ON
创建事件

使用CREATE EVENT语句创建事件:

DELIMITER //
CREATE EVENT event_name
ON SCHEDULE schedule
[ON COMPLETION [NOT] PRESERVE]
[ENABLE | DISABLE | DISABLE ON SLAVE]
[COMMENT 'comment']
DO
BEGIN-- SQL语句
END //
DELIMITER ;

schedule可以是以下之一:

  • AT timestamp:在指定时间执行一次
  • EVERY interval:按指定间隔重复执行

示例:

-- 创建一次性事件
DELIMITER //
CREATE EVENT one_time_event
ON SCHEDULE AT '2023-12-31 23:59:59'
DO
BEGININSERT INTO year_end_summary (year, total_sales)SELECT YEAR(order_date), SUM(amount)FROM ordersWHERE YEAR(order_date) = 2023;
END //
DELIMITER ;-- 创建重复事件
DELIMITER //
CREATE EVENT daily_cleanup
ON SCHEDULE EVERY 1 DAY
STARTS '2023-01-01 01:00:00'
DO
BEGINDELETE FROM temp_logsWHERE created_at < DATE_SUB(NOW(), INTERVAL 7 DAY);
END //
DELIMITER ;
查看事件

可以使用以下命令查看事件:

-- 查看所有事件
SHOW EVENTS;-- 查看特定数据库的事件
SHOW EVENTS FROM your_database;

也可以从INFORMATION_SCHEMA查询事件信息:

SELECT event_name, event_definition, interval_value, interval_field, status
FROM INFORMATION_SCHEMA.EVENTS
WHERE event_schema = 'your_database';
修改事件

使用ALTER EVENT语句修改事件:

-- 修改事件执行计划
ALTER EVENT daily_cleanup
ON SCHEDULE EVERY 12 HOUR;-- 禁用事件
ALTER EVENT daily_cleanup
DISABLE;-- 启用事件
ALTER EVENT daily_cleanup
ENABLE;
删除事件

使用DROP EVENT语句删除事件:

DROP EVENT [IF EXISTS] event_name;
事件的使用场景

事件调度器适用于以下场景:

  1. 定期数据清理:删除旧日志或临时数据
  2. 定期数据聚合:计算和存储统计信息
  3. 定期维护任务:优化表、更新统计信息
  4. 生成定期报告:每日、每周或每月报告
  5. 数据归档:将旧数据移动到归档表

4.3.7 分区

分区是将大表分成更小、更易管理的部分的技术。MySQL支持多种分区类型。

分区类型

MySQL支持以下分区类型:

  1. RANGE分区:基于连续范围的分区
  2. LIST分区:基于离散值列表的分区
  3. HASH分区:基于哈希函数的分区
  4. KEY分区:类似于HASH,但使用MySQL的内部哈希函数
创建分区表

使用PARTITION BY子句创建分区表:

-- RANGE分区
CREATE TABLE sales (id INT NOT NULL,sale_date DATE NOT NULL,amount DECIMAL(10,2),PRIMARY KEY (id, sale_date)  -- 包含分区键
)
PARTITION BY RANGE (YEAR(sale_date)) (PARTITION p0 VALUES LESS THAN (2020),PARTITION p1 VALUES LESS THAN (2021),PARTITION p2 VALUES LESS THAN (2022),PARTITION p3 VALUES LESS THAN (2023),PARTITION p4 VALUES LESS THAN MAXVALUE
);-- LIST分区
CREATE TABLE employees (id INT NOT NULL,name VARCHAR(50),department VARCHAR(20),PRIMARY KEY (id, department)  -- 包含分区键
)
PARTITION BY LIST (department) (PARTITION p_sales VALUES IN ('Sales', 'Marketing'),PARTITION p_tech VALUES IN ('IT', 'Engineering'),PARTITION p_admin VALUES IN ('HR', 'Finance', 'Admin')
);-- HASH分区
CREATE TABLE orders (id INT NOT NULL,customer_id INT,order_date DATE,PRIMARY KEY (id)
)
PARTITION BY HASH (id)
PARTITIONS 4;-- KEY分区
CREATE TABLE customers (id INT NOT NULL,name VARCHAR(50),region VARCHAR(50),PRIMARY KEY (id)
)
PARTITION BY KEY (id)
PARTITIONS 4;
子分区

可以进一步将分区分成子分区:

CREATE TABLE sales (id INT NOT NULL,sale_date DATE NOT NULL,amount DECIMAL(10,2),region VARCHAR(10),PRIMARY KEY (id, sale_date, region)
)
PARTITION BY RANGE (YEAR(sale_date))
SUBPARTITION BY KEY (region)
SUBPARTITIONS 2 (PARTITION p0 VALUES LESS THAN (2020),PARTITION p1 VALUES LESS THAN (2021),PARTITION p2 VALUES LESS THAN (2022)
);
管理分区

可以使用ALTER TABLE语句管理分区:

-- 添加分区
ALTER TABLE sales
ADD PARTITION (PARTITION p5 VALUES LESS THAN (2024));-- 删除分区
ALTER TABLE sales
DROP PARTITION p0;-- 重组分区
ALTER TABLE sales
REORGANIZE PARTITION p1, p2 INTO (PARTITION p12 VALUES LESS THAN (2022)
);-- 拆分分区
ALTER TABLE sales
REORGANIZE PARTITION p4 INTO (PARTITION p4 VALUES LESS THAN (2023),PARTITION p5 VALUES LESS THAN MAXVALUE
);
分区修剪

分区修剪是MySQL优化器的一个功能,它只扫描包含查询数据的分区,而不是整个表:

-- 这个查询只会扫描p1分区
SELECT * FROM sales
WHERE sale_date BETWEEN '2020-01-01' AND '2020-12-31';
查看分区信息

可以使用以下命令查看分区信息:

-- 查看表的分区信息
SHOW CREATE TABLE sales;-- 查看分区详细信息
SELECT partition_name, partition_method, partition_expression
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE table_name = 'sales';-- 查看每个分区的行数
SELECT partition_name, table_rows
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE table_name = 'sales';
分区的优势

分区提供以下优势:

  1. 提高查询性能:通过分区修剪减少扫描的数据量
  2. 简化数据管理:可以单独管理每个分区
  3. 优化维护操作:可以对单个分区执行维护操作
  4. 提高可用性:一个分区的问题不会影响其他分区
分区的限制

分区也有一些限制:

  1. 分区键必须是主键的一部分
  2. 不支持外键约束
  3. 某些存储引擎不支持分区
  4. 分区数量有限制(最多1024个分区)

4.3.8 全文搜索

MySQL支持全文搜索,允许基于文本内容的复杂搜索。

创建全文索引

可以在创建表时或之后创建全文索引:

-- 在创建表时创建全文索引
CREATE TABLE articles (id INT PRIMARY KEY,title VARCHAR(200),content TEXT,FULLTEXT INDEX idx_content (content)
);-- 在现有表上创建全文索引
CREATE FULLTEXT INDEX idx_title_content ON articles (title, content);
全文搜索模式

MySQL支持三种全文搜索模式:

  1. 自然语言模式:搜索包含任何指定词的文档
  2. 布尔模式:使用特殊运算符进行更复杂的搜索
  3. 查询扩展模式:基于初始搜索结果扩展搜索
自然语言模式

自然语言模式是默认模式,它搜索包含任何指定词的文档:

SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('database optimization');

这将返回包含"database"或"optimization"的文章,按相关性排序。

布尔模式

布尔模式允许使用特殊运算符进行更复杂的搜索:

SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('database optimization' IN BOOLEAN MODE);

布尔模式运算符:

  • +:词必须存在
  • -:词不能存在
  • *:通配符
  • ":精确短语
  • ():分组
  • >:增加相关性
  • <:减少相关性

示例:

-- 必须包含"database",可能包含"optimization"
SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('+database optimization' IN BOOLEAN MODE);-- 必须包含"database",不能包含"mysql"
SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('+database -mysql' IN BOOLEAN MODE);-- 必须包含精确短语"database optimization"
SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('"database optimization"' IN BOOLEAN MODE);-- 包含以"data"开头的词
SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('data*' IN BOOLEAN MODE);
查询扩展模式

查询扩展模式执行两次搜索:第一次使用原始搜索词,第二次使用第一次搜索中找到的相关词:

SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('database' WITH QUERY EXPANSION);

这可能会返回不包含"database"但包含相关词(如"MySQL"、"SQL"等)的文章。

全文搜索配置

可以配置全文搜索的行为:

-- 最小词长度(默认为3)
SET GLOBAL innodb_ft_min_token_size = 2;-- 停用词(不索引的常见词)
SET GLOBAL innodb_ft_server_stopword_table = 'database/stopwords';

注意:修改这些设置后,需要重建全文索引才能生效。

4.3.9 JSON支持

MySQL 5.7.8及以上版本支持原生JSON数据类型,提供了存储和操作JSON数据的功能。

创建JSON列

可以在创建表时定义JSON列:

CREATE TABLE products (id INT PRIMARY KEY,name VARCHAR(100),attributes JSON
);
插入JSON数据

可以使用JSON字面量或JSON_OBJECT()函数插入JSON数据:

-- 使用JSON字面量
INSERT INTO products VALUES (1, 'Laptop', '{"color": "black", "weight": 1.5, "features": ["backlit keyboard", "touch screen"]}');-- 使用JSON_OBJECT()函数
INSERT INTO products VALUES (2, 'Phone', JSON_OBJECT('color', 'white', 'weight', 0.3, 'features', JSON_ARRAY('water resistant', 'dual camera')));
查询JSON数据

可以使用JSON函数和运算符查询JSON数据:

-- 使用->运算符(返回JSON值)
SELECT id, name, attributes->'$.color' AS color FROM products;-- 使用->>运算符(返回字符串值)
SELECT id, name, attributes->>'$.color' AS color FROM products;-- 访问数组元素
SELECT id, name, attributes->'$.features[0]' AS first_feature FROM products;-- 使用JSON_EXTRACT()函数
SELECT id, name, JSON_EXTRACT(attributes, '$.color') AS color FROM products;
修改JSON数据

可以使用JSON函数修改JSON数据:

-- 更新整个JSON值
UPDATE products
SET attributes = '{"color": "silver", "weight": 1.5, "features": ["backlit keyboard", "touch screen", "fingerprint reader"]}'
WHERE id = 1;-- 更新特定路径
UPDATE products
SET attributes = JSON_SET(attributes, '$.color', 'silver', '$.features[2]', 'fingerprint reader')
WHERE id = 1;-- 插入新属性
UPDATE products
SET attributes = JSON_INSERT(attributes, '$.price', 999.99)
WHERE id = 1;-- 替换属性
UPDATE products
SET attributes = JSON_REPLACE(attributes, '$.weight', 1.6)
WHERE id = 1;-- 删除属性
UPDATE products
SET attributes = JSON_REMOVE(attributes, '$.weight')
WHERE id = 1;
JSON函数

MySQL提供了许多JSON函数:

  1. 构造函数

    • JSON_ARRAY():创建JSON数组
    • JSON_OBJECT():创建JSON对象
    • JSON_QUOTE():将字符串引用为JSON字符串
  2. 查询函数

    • JSON_EXTRACT():提取JSON值
    • JSON_CONTAINS():检查JSON文档是否包含特定值
    • JSON_CONTAINS_PATH():检查JSON文档是否包含特定路径
    • JSON_KEYS():返回JSON对象的键
    • JSON_SEARCH():查找JSON值中的字符串
  3. 修改函数

    • JSON_INSERT():插入值(如果路径不存在)
    • JSON_SET():插入或更新值
    • JSON_REPLACE():更新值(如果路径存在)
    • JSON_REMOVE():删除值
    • JSON_ARRAY_APPEND():将值追加到JSON数组
    • JSON_ARRAY_INSERT():将值插入JSON数组
  4. 实用函数

    • JSON_TYPE():返回JSON值的类型
    • JSON_LENGTH():返回JSON文档的长度
    • JSON_VALID():检查值是否为有效的JSON
    • JSON_PRETTY():格式化JSON文档以提高可读性
JSON索引

虽然不能直接索引JSON列,但可以创建虚拟列并索引它们:

-- 添加虚拟列
ALTER TABLE products
ADD COLUMN color VARCHAR(50) GENERATED ALWAYS AS (attributes->>'$.color') VIRTUAL,
ADD COLUMN weight DECIMAL(5,2) GENERATED ALWAYS AS (attributes->>'$.weight') VIRTUAL;-- 创建索引
CREATE INDEX idx_color ON products(color);
CREATE INDEX idx_weight ON products(weight);

然后可以使用这些索引进行高效查询:

SELECT * FROM products
WHERE color = 'black' AND weight < 1.0;

4.3.10 性能优化

MySQL性能优化是一个广泛的主题,涉及多个方面。以下是一些关键的优化技术:

查询优化
  1. 使用EXPLAIN分析查询
EXPLAIN SELECT * FROM employees
WHERE department_id = 60 AND salary > 10000;

EXPLAIN输出包含以下重要信息:

  • select_type:查询类型(SIMPLE、PRIMARY、SUBQUERY等)
  • table:表名
  • type:连接类型(system、const、eq_ref、ref、range、index、ALL等)
  • possible_keys:可能使用的索引
  • key:实际使用的索引
  • key_len:索引键的长度
  • ref:与索引比较的列
  • rows:估计要检查的行数
  • filtered:按表条件过滤的行百分比
  • Extra:附加信息
  1. 优化索引使用

    • 为WHERE、JOIN、ORDER BY和GROUP BY子句中的列创建索引
    • 使用复合索引时,考虑列的顺序
    • 避免在索引列上使用函数
  2. 优化JOIN操作

    • 确保JOIN条件有索引
    • 使用适当的JOIN类型(INNER、LEFT、RIGHT)
    • 考虑表的连接顺序
  3. 优化子查询

    • 考虑使用JOIN替代某些子查询
    • 使用EXISTS而不是IN(对于大型子查询)
  4. 使用LIMIT限制结果集大小

服务器配置优化
  1. 内存配置

    • innodb_buffer_pool_size:InnoDB缓冲池大小(通常设置为系统内存的50-80%)
    • key_buffer_size:MyISAM键缓存大小
    • query_cache_size:查询缓存大小(MySQL 8.0已移除)
    • sort_buffer_size:排序缓冲区大小
    • join_buffer_size:连接缓冲区大小
  2. 并发配置

    • max_connections:最大连接数
    • thread_cache_size:线程缓存大小
    • innodb_thread_concurrency:InnoDB线程并发数
  3. 日志配置

    • innodb_log_file_size:InnoDB日志文件大小
    • innodb_log_buffer_size:InnoDB日志缓冲区大小
    • innodb_flush_log_at_trx_commit:事务提交时的日志刷新策略
表优化
  1. 选择适当的存储引擎

    • InnoDB:支持事务、外键、行级锁定
    • MyISAM:简单、快速、不支持事务
    • MEMORY:内存表,速度快但不持久
  2. 表结构优化

    • 使用适当的数据类型
    • 避免使用NULL(除非必要)
    • 考虑表分区
    • 使用适当的字符集和排序规则
  3. 表维护

    • 定期优化表:OPTIMIZE TABLE
    • 分析表:ANALYZE TABLE
    • 检查表:CHECK TABLE
    • 修复表:REPAIR TABLE
监控和诊断
  1. 性能模式(Performance Schema)

    • 启用性能模式:SET GLOBAL performance_schema = ON;
    • 查询性能模式表获取性能信息
  2. 慢查询日志

    • 启用慢查询日志:SET GLOBAL slow_query_log = 1;
    • 设置慢查询阈值:SET GLOBAL long_query_time = 1;
    • 分析慢查询日志:使用mysqldumpslow工具
  3. 状态变量

    • 查看全局状态:SHOW GLOBAL STATUS;
    • 查看会话状态:SHOW SESSION STATUS;
    • 查看特定变量:SHOW STATUS LIKE 'Com_%';
  4. 系统变量

    • 查看全局变量:SHOW GLOBAL VARIABLES;
    • 查看会话变量:SHOW SESSION VARIABLES;
    • 查看特定变量:SHOW VARIABLES LIKE 'innodb_%';
缓存优化
  1. 查询缓存(MySQL 8.0已移除):

    • 启用查询缓存:SET GLOBAL query_cache_type = 1;
    • 设置查询缓存大小:SET GLOBAL query_cache_size = 67108864;
  2. InnoDB缓冲池

    • 设置缓冲池大小:SET GLOBAL innodb_buffer_pool_size = 1073741824;
    • 设置缓冲池实例数:SET GLOBAL innodb_buffer_pool_instances = 8;
  3. 表缓存

    • 设置表打开缓存:SET GLOBAL table_open_cache = 2000;
    • 设置表定义缓存:SET GLOBAL table_definition_cache = 1400;

通过掌握这些高级功能和优化技术,您可以充分利用MySQL的强大功能,构建高性能、可靠的数据库应用程序。这些功能不仅可以提高数据库的性能和可靠性,还可以简化开发和维护工作。

http://www.xdnf.cn/news/903169.html

相关文章:

  • uniapp Vue2 获取电量的独家方法:绕过官方插件限制
  • Amazon Bedrock 助力 SolveX.AI 构建智能解题 Agent,打造头部教育科技应用
  • 当丰收季遇上超导磁测量:粮食产业的科技新征程
  • 智能手表健康监测系统的PSRAM存储芯片CSS6404LS-LI—高带宽、耐高温、微尺寸的三重突破
  • 微算法科技(NASDAQ:MLGO)基于信任的集成共识和灰狼优化(GWO)算法,搭建高信任水平的区块链网络
  • Guava LoadingCache 使用指南
  • Web前端基础:HTML-CSS
  • D3ctf-web-d3invitation单题wp
  • Q: dify前端使用哪些开发框架?
  • Houdini POP入门学习05 - 物理属性
  • 无头浏览器技术:Python爬虫如何精准模拟搜索点击
  • 每日八股文6.6
  • PowerBI企业运营分析—列互换式中国式报表分析
  • 【应用】Ghost Dance:利用惯性动捕构建虚拟舞伴
  • 单片机内部结构基础知识 FLASH相关解读
  • 数据集-目标检测系列- 口红嘴唇 数据集 lips >> DataBall
  • windows10搭建nfs服务器
  • Linux中 SONAME 的作用
  • mysql-MySQL体系结构和存储引擎
  • 《UE5_C++多人TPS完整教程》学习笔记37 ——《P38 变量复制(Variable Replication)》
  • Xsens-AAA工作室品质,为动画师准备
  • 中科院1区顶刊|IF14+:多组学MR联合单细胞时空分析,锁定心血管代谢疾病的免疫治疗新靶点
  • Bootstrap 5 文件结构与 API 使用指南
  • 从EDR到XDR:终端安全防御体系演进实践指南
  • 汽车免拆诊断案例 | 2010款捷豹XFL车制动警告灯、DSC警告灯异常点亮
  • curl获取ip定位信息 --- system(一)
  • Git版本控制工具详解
  • 电脑定时关机工具推荐
  • scss(sass)中 的使用说明
  • 装载机防撞系统:智能守护,筑牢作业现场人员安全防线