JAVA进阶

存储架构优化的那些事(三)

2021-09-01  本文已影响0人  勤_
mysql.jpeg

概述

上文我们具体的深入Mysql SQL优化的相关方案,本文将深入Mysql 索引优化的方案。

初始化脚本

通过如下脚本,在mysql数据库中新建对应的实验表和数据。

CREATE TABLE `user_info` (
  `id`   BIGINT(20)  NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(50) NOT NULL DEFAULT '',
  `age`  INT(11)              DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `name_index` (`name`)
)
  ENGINE = INNODB
  DEFAULT CHARSET = utf8;

INSERT INTO user_info (NAME, age) VALUES ('xys', 20);
INSERT INTO user_info (NAME, age) VALUES ('a', 21);
INSERT INTO user_info (NAME, age) VALUES ('b', 23);
INSERT INTO user_info (NAME, age) VALUES ('c', 50);
INSERT INTO user_info (NAME, age) VALUES ('d', 15);
INSERT INTO user_info (NAME, age) VALUES ('e', 20);
INSERT INTO user_info (NAME, age) VALUES ('f', 21);
INSERT INTO user_info (NAME, age) VALUES ('g', 23);
INSERT INTO user_info (NAME, age) VALUES ('h', 50);
INSERT INTO user_info (NAME, age) VALUES ('i', 15);

CREATE TABLE `order_info` (
  `id`           BIGINT(20)  NOT NULL AUTO_INCREMENT,
  `user_id`      BIGINT(20)           DEFAULT NULL,
  `product_name` VARCHAR(50) NOT NULL DEFAULT '',
  `productor`    VARCHAR(30)          DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `user_product_detail_index` (`user_id`, `product_name`, `productor`)
)
  ENGINE = INNODB
  DEFAULT CHARSET = utf8;

INSERT INTO order_info (user_id, product_name, productor) VALUES (1, 'p1', 'WHH');
INSERT INTO order_info (user_id, product_name, productor) VALUES (1, 'p2', 'WL');
INSERT INTO order_info (user_id, product_name, productor) VALUES (1, 'p1', 'DX');
INSERT INTO order_info (user_id, product_name, productor) VALUES (2, 'p1', 'WHH');
INSERT INTO order_info (user_id, product_name, productor) VALUES (2, 'p5', 'WL');
INSERT INTO order_info (user_id, product_name, productor) VALUES (3, 'p3', 'MA');
INSERT INTO order_info (user_id, product_name, productor) VALUES (4, 'p1', 'WHH');
INSERT INTO order_info (user_id, product_name, productor) VALUES (6, 'p1', 'WHH');
INSERT INTO order_info (user_id, product_name, productor) VALUES (9, 'p8', 'TE');
INSERT INTO order_info (user_id, product_name, productor) VALUES (1, 'p199', 'WHH99');

-- 验证分区 
CREATE TABLE user_temp (
  id   INT UNSIGNED NOT NULL AUTO_INCREMENT,
  NAME VARCHAR(20),
  PRIMARY KEY (id)
)ENGINE = INNODB PARTITION BY KEY (id) PARTITIONS 3;

INSERT INTO user_temp VALUES(1,"hello") ;
INSERT INTO user_temp VALUES(2,"world") ;
INSERT INTO user_temp VALUES(3,"nice") ;

DROP PROCEDURE IF EXISTS batchInsert; 

-- 批量插入数据
DELIMITER //
CREATE PROCEDURE batchInsert()
BEGIN
    DECLARE num INT; 
    SET num=20;
    WHILE num<=100000 DO
        INSERT INTO user_info (id, NAME, age) VALUES (num ,CONCAT('xys',num) , 20);
        INSERT INTO order_info (user_id, product_name, productor) VALUES (num, CONCAT('p',num) , CONCAT('WHH',num));
        SET num=num+1;
    END WHILE;
END
// 
DELIMITER ; #恢复;表示结束
CALL batchInsert;

SELECT COUNT(1) FROM `user_info`;
SELECT COUNT(1) FROM `order_info`;

-- user_info增加一列
ALTER TABLE user_info ADD COLUMN `oid` BIGINT(20);
UPDATE user_info u , order_info o SET u.oid = o.user_id WHERE o.user_id = u.id ;

ALTER TABLE order_info ADD COLUMN `description` VARCHAR(255) ;

-- Index Prefixes
CREATE TABLE test(blob_col BLOB);
SHOW VARIABLES LIKE 'InnoDB_large_prefix';
SET GLOBAL InnoDB_large_prefix=off;
ALTER TABLE test ADD INDEX idx_blob_col(blob_col(7600));

-- 
CREATE TABLE t1 (
  i1 INT NOT NULL DEFAULT 0,
  i2 INT NOT NULL DEFAULT 0,
  d DATE DEFAULT NULL,
  PRIMARY KEY (i1, i2),
  INDEX k_d (d)
) ENGINE = INNODB;

INSERT INTO t1 VALUES
(1, 1, '1998-01-01'), (1, 2, '1999-01-01'),
(1, 3, '2000-01-01'), (1, 4, '2001-01-01'),
(1, 5, '2002-01-01'), (2, 1, '1998-01-01'),
(2, 2, '1999-01-01'), (2, 3, '2000-01-01'),
(2, 4, '2001-01-01'), (2, 5, '2002-01-01'),
(3, 1, '1998-01-01'), (3, 2, '1999-01-01'),
(3, 3, '2000-01-01'), (3, 4, '2001-01-01'),
(3, 5, '2002-01-01'), (4, 1, '1998-01-01'),
(4, 2, '1999-01-01'), (4, 3, '2000-01-01'),
(4, 4, '2001-01-01'), (4, 5, '2002-01-01'),
(5, 1, '1998-01-01'), (5, 2, '1999-01-01'),
(5, 3, '2000-01-01'), (5, 4, '2001-01-01'),
(5, 5, '2002-01-01');

优化索引

总体方向:

提高 SELECT 操作性能的最佳方法是为查询中测试的一个或多个列创建索引。索引条目的作用类似于指向表行的指针,允许查询快速确定 WHERE 子句中哪些行与条件匹配,并检索这些行的其他列值。

尽管为查询中使用的每个可能列创建索引很诱人,但是不必要的索引会浪费 MySQL 的空间和时间来决定使用哪些索引。索引还会增加插入、更新和删除的成本,因为每个索引都必须更新。

索引用于快速查找具有特定列值的行。如果没有索引,MySQL 必须从第一行开始,然后通读整个表以找到相关的行。如果表中有相关列的索引,MySQL 可以快速确定要在数据文件中间查找的位置,而无需查看所有数据。这比按顺序读取每一行要快得多。

大多数 MySQL 索引(primarykey、 UNIQUE、 INDEX 和 FULLTEXT)都存储在 b 树中。

细分方向:

参考

Optimization and Indexes

上一篇下一篇

猜你喜欢

热点阅读