SELECT * FROM tb_name PROCEDURE ANALYSE()
-- 建表 mysql> CREATE TABLE DUCK_CUST( -> cust_num MEDIUMINT AUTO_INCREMENT, -> cust_title TINYINT, -> cust_last CHAR(20) NOT NULL, -> cust_first CHAR(15) NOT NULL, -> cust_suffix ENUM('Jr.', 'II', 'III', 'IV', 'V', 'M.D.', 'PhD'), -> cust_add1 CHAR(30) NOT NULL, -> cust_add2 CHAR(10), -> cust_city CHAR(18) NOT NULL, -> cust_state CHAR(2) NOT NULL, -> cust_zip1 CHAR(5) NOT NULL, -> cust_zip2 CHAR(4), -> cust_duckname CHAR(25) NOT NULL, -> cust_duckday DATE, -> PRIMARY KEY (cust_num) )ENGINE=MyISAM; #插入数据 ... #查看表优化 mysql> SELECT * FROM DUCK_CUST PROCEDURE ANALYSE()\G *************************** 1. row *************************** Field_name: test.DUCK_CUST.cust_num Min_value: 1 Max_value: 1 Min_length: 1 Max_length: 1 Empties_or_zeros: 0 Nulls: 0 Avg_value_or_avg_length: 1.0000 Std: 0.0000 Optimal_fieldtype: ENUM('1') NOT NULL *************************** 2. row *************************** Field_name: test.DUCK_CUST.cust_title Min_value: 1 Max_value: 1 Min_length: 1 Max_length: 1 ... 可见由于cust_num数据Max_length, Min_length, Avg_value_or_avg_length, 长度均为1,所以建议用MEDIUMINT(2)
1. 第一种方法是垂直拆分,即把主键和一些列放到一个表,然后把主键和其他一些列放到另一个表中。这样可以把常用列和非常用列分开,一定程度上减少I/O次数,但需要管理冗余列,查询所有数据需要JOIN操作。
2. 第二种方法是水平拆分,根据一列或多列的值,把数据行放到两个独立的表中。表很大,分割后可以降低在查询时所需要读的数据和索引的页数;表中数据本来就有独立性,比如有些数据常用,有些不常用。需要把数据存放在多个介质中。
1. 增加冗余列:指多个表中具有相同的列,避免连接查询。
2. 增加派生列:指增加的列来自其他表中的数据,由其他表中的数据经过计算生成,以减少连接查询和集函数的使用。
3. 重新组表:指如果许多用户需要查询两个表的数据,则把他们组合成一张表,以减少连接查询。
4. 分割表:把常用列与非常用列等可以分开保存,减少查询的I/O。
1. 定时批处理更新。
2. 在逻辑实现中实现同步。
3. 触发器同步执行。
# 建表 mysql> CREATE TABLE session( -> cust_id VARCHAR(10), -> cust_amount DECIMAL(16,2), -> cust_date DATE, -> cust_ip VARCHAR(20)); Query OK, 0 rows affected (0.36 sec) # 插入大量数据后 ... # 查询特定用户的消费总金额 mysql> SELECT sum(cust_amount) FROM session WHERE cust_id='123'; +------------------+ | sum(cust_amount) | +------------------+ | 25585254.40 | +------------------+ 1 row in set (5.81 sec) # 若先将记录转移到中间表 mysql> CREATE TABLE tmp_session( -> cust_id VARCHAR(10), -> cust_amount DECIMAL(16, 2), -> cust_date DATE, -> cust_ip VARCHAR(20)); Query OK, 0 rows affected (0.72 sec) #将数据先放到中间表 mysql> INSERT INTO tmp_session SELECT * FROM session WHERE cust_id='123'; Query OK, 2097152 rows affected (21.19 sec) Records: 2097152 Duplicates: 0 Warnings: 0 mysql> SELECT sum(cust_amount) FROM tmp_session; +------------------+ | sum(cust_amount) | +------------------+ | 25585254.40 | +------------------+ 1 row in set (1.76 sec)
1. 中间表复制源表部分数据,并且与源表相隔离,在中间表上做统计查询不会对在线应用产生负面影响。
2. 中间表上可以灵活的添加索引或增加临时用的新字段,从而达到提高统计查询效率和辅助统计查询作用。
不吝指正。