设为首页 收藏本站
查看: 1034|回复: 0

[经验分享] MySQL的经典用法----临时表与内存表

[复制链接]

尚未签到

发表于 2018-10-9 12:26:01 | 显示全部楼层 |阅读模式
  mysql5.5性能优化-内存表
  临时表与内存表
  内存表分为2种,但共同点是,重起数据库以后,内存中的数据全部丢失,内存表的功能有部分的限制,有些属性不能像正常表一样使用,所以请大家使用的时候谨慎参照官方文档.下面只是抛砖引玉.
  1.临时表:表建在内存里,数据在内存里
  2.内存表:表建在磁盘里,数据在内存里
  其中包括2个重要的参数
  [mysqld]
  # 内存表容量
  max_heap_table_size=1024M
  # 临时表容量
  tmp_table_size=1024M
  建立内存表的时候,在5.5里,需要指定表的引擎类型 ENGINE=MEMORY
  CREATE TABLE coldtest_vardata (

  >  name varchar(255)
  ) ENGINE=MEMORY DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
  临时表
  create temporary table tmp1(id int not null);
  其他常用参数
  # skip hostname,just use ip
  skip-name-resolve
  # auto start event
  event_scheduler=1
  2 . Mysql 5.5 无法远程登陆:Can't get hostname for your address
  错误信息:Can't get hostname for your address
  修改配置文件
  在windows下面,文件时my.ini,在Linux下面是my.cnf
  解决方案是在
  [mysqld]
  skip-name-resolve                      #加上这一个属性
  它将禁止 MySQL Server 对外部连接进行 DNS 解析,使用这一选项可以消除 MySql 进行 DNS 解析的时间。
  但需要注意,如果开启该选项,则所有远程主机连接授权都要使用IP地址方式,否则MySQL将无法正常处理连接请求。
  可以这么理解mysql处理客户端解析的过程:
  1,当 mysql client 发起连接请求时,MySql Server 会主动去查 client 的主机名。
  2,首先查找Windows系统目录下 /etc/hosts 文件,搜索域名和IP的对应关系。
  3,如果hosts文件没有,则查找DNS设置,如果没有设置DNS服务器,会立刻返回失败;如果设置了DNS服务器,就进行反向解析,直到timeout。
  注意:如果开启 skip-name-resolve 选项,要确认 MySql 是否采用过主机名的授权,
  在 mysql 中运行如下命令:
  mysql> select user,host from mysql.user where host  'localhost' ;
  一般会得到以“%”授权(也就是任何地址)的记录:
  +------------------+-------------+
  | user             | host        |
  +------------------+-------------+
  | root             | %           |
  | user_sync | 192.168.0.113 |
  如果有host名是什么“DB1”“DB2”的,那么删除授权表中有 hostanme 的记录,然后重启mysqld。
  3。mysql JDBC 驱动常用的有两个,一个是gjt(Giant Java Tree)组织提供的mysql驱动,其JDBC Driver名称(JAVA类名)为:org.gjt.mm.mysql.Driver
  详情请参见网站:http://www.gjt.org/另一个是mysql官方提供的JDBC Driver,其Java类名为:com.mysql.jdbc.Driver
  驱动下载网址:http://dev.mysql.com/downloads/,进入其中的MySQL Connector/J区域下载。
  mysql JDBC URL格式如下:
  jdbc:mysql://[host:port]/[database][?参数名1][=参数值1][&参数名2][=参数值2]...
  参数名称
  参数说明
  缺省值
  最低版本要求
  user
  数据库用户名(用于连接数据库)
  所有版本
  password
  用户密码(用于连接数据库)
  所有版本
  useUnicode
  是否使用Unicode字符集,如果参数characterEncoding设置为gb2312或gbk,本参数值必须设置为true
  false
  1.1g
  characterEncoding
  当useUnicode设置为true时,指定字符编码。比如可设置为gb2312或gbk
  false
  1.1g
  autoReconnect
  当数据库连接异常中断时,是否自动重新连接?
  false
  1.1
  autoReconnectForPools
  是否使用针对数据库连接池的重连策略
  false
  3.1.3
  failOverReadOnly
  自动重连成功后,连接是否设置为只读
  true
  3.0.12
  maxReconnects
  autoReconnect设置为true时,重试连接的次数
  3
  1.1
  initialTimeout
  autoReconnect设置为true时,两次重连之间的时间间隔,单位:秒
  2
  1.1
  connectTimeout
  和数据库服务器建立socket连接时的超时,单位:毫秒。 0表示永不超时,适用于JDK 1.4及更高版本
  0
  3.0.1
  socketTimeout
  socket操作(读写)超时,单位:毫秒。0表示永不超时
  0
  3.0.1
  对应中文环境,通常mysql连接URL可以设置为:
  jdbc:mysql://localhost:3306/test?user=root&password=&useUnicode=true&characterEncoding=gbk&autoReconnect=true&failOverReadOnly=false
  在使用数据库连接池的情况下,最好设置如下两个参数:
  autoReconnect=true&failOverReadOnly=false
  需要注意的是,在xml配置文件中,url中的&符号需要转义。比如在tomcat的server.xml中配置数据库连接池时,mysql jdbc url样例如下:
  jdbc:mysql://localhost:3306/test?user=root&password=&useUnicode=true&characterEncoding=gbk
  4. Mysql 的定时备份过程
  mysql支持命令行导入导出数据文件,格式是*.sql
  1)导入:
  mysql -u用户名 -p密码 数据库名 < 文件路径\文件名
  2)导出:
  mysqldump -u用户名 -p密码 数据库名 > 文件路径\文件名
  3)真实案例
  本人是在windows 2003 开发服务器上,实现了定时自动备份
  一般文件名,用日期和时间.sql来使用.下面是我的*.bat批处理文件
  总共3行:
  第一行,表示切换到d盘
  第二行,找到mysql安装目录的bin目录,这样不需要设置环境变量
  第三行,导出*.sql文件,同时使用当前时间作为文件名,格式如下:cold_20101026_1244.sql,表示cold数据库,在2010年10月26日,中午12点44分生成的备份文件
  d:
  cd D:\Program Files\MySQL\MySQL Server 5.1\bin
  mysqldump -uroot -p123456 cold >  d:\mysql_data\cold_%date:~0,4%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2%.sql
  然后,将该批处理文件,加到windows任务计划中,
  点击 控制面板>任务计划>添加任务计划。
  顺便给出还原代码,还原的时候要首先手工建立数据库,默认情况下,是不会自动创建数据库的
  d:
  cd D:\Program Files\MySQL\MySQL Server 5.1\bin
  mysql -uroot -p147258369 cold < D:\mysql_data\cold_20101026_1234.sql
  注:Oracle的备份,也可以这么实现,跨平台也是如此,需要把脚本加到任务计划中来。
  5.mysql的性能优化使用技巧
  在windows下,配置文件为%mysql_home%/my.ini
  在linux下,配制文件为/etc/my.cnf
  一 性能优化
  1--------INNODB_BUFFER_POOL_SIZE
  该参数是innodb引擎的最主要的性能参数,对数据库的性能起了决定性作用.说白了就是数据库的使用内存.
  2--------性能分析,
  show status like '%'; #查看数据库状态
  show variables like %; #查看数据库的变量
  show engine innodb status\G; #查看innodb的监控状态
  二 使用技巧
  1--------字符集尽量使用uft-8,这样更容易解决乱码问题,在linux下修改my.cnf的3处,修改前后可以通过命令
  show variables like 'character%';
  查看字符集状态.
  找到客户端配置[client] 在下面添加
  #默认字符集为utf8
  default-character-set=utf8
  在找到[mysqld] 添加
  #默认字符集为utf8
  default-character-set=utf8
  #设定连接mysql数据库时使用utf8编码,以让mysql数据库为utf8运行
  init_connect='SET NAMES utf8'
  6.mysql统计数据 ,但是空的数据也要显示
  在实际中,有这样一个需求,就是需要统计24个小时的相关数据.有的朋友认为简单的一句group by就可以解决。其实不然,真正的统计,24个小时都得有数据的,不允许出现缺失的现象.其实这个有点像废话,处理结果集ResultSet也可以,但为了减少JAVA的负担和增强java代码的可读性,所以尽量用SQL语句,一次性把数据处理好.
  表结构,有三个字段一看就明白
  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   CREATE TABLE `vardata` (
  •   `Id` int(11) NOT NULL AUTO_INCREMENT,
  •   `name` varchar(255) DEFAULT NULL,
  •   `time` datetime DEFAULT '0000-00-00 00:00:00',
  •   `data` double(15,5) DEFAULT '0.00000',
  •   PRIMARY KEY (`Id`,`time`),
  •   UNIQUE KEY `unique` (`name`,`time`)
  •   )
  下面我想统计12个月的每月数据,如果数据存在,则显示数据;如果数据不存在,则现实我们约定的错误码(-601).下面只是给出了3条SQL语句提供样例.不管存不存在数据,肯定会查出3条记录来.
  在真正的开发中,要把其中前面的time和后面where里的time,用所查询的语句,动态组装.如果朋友们还不理解,就给我留言吧 ^-^
  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   select if(count(*)=0,-601,data) as data,'2011-07-12 10:40:00' as time from vardata where time='2011-07-12 10:40:00'
  •   union
  •   select if(count(*)=0,-601,data) as data,'2012-08-12 10:40:00' as time from vardata where time='2012-08-12 10:40:00'
  •   union
  •   select if(count(*)=0,-601,data) as data,'2013-09-12 10:40:00' as time from vardata where time='2013-09-12 10:40:00';
  7.mysql中动态sql语句的用法
  在存储过程中,动态拼接一个字符串,然后执行之.
  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   DROP PROCEDURE IF EXISTS demoSp;
  •   CREATE PROCEDURE demoSp()
  •   BEGIN
  •   set @sqlstr=concat("select count(*) from ", "dual");
  •   prepare stmt from @sqlstr;
  •   EXECUTE stmt;
  •   deallocate prepare stmt;
  •   END;
  8.mysql中的触发器

  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   CREATE TABLE `vardata` (
  •   `Id` int(11) NOT NULL AUTO_INCREMENT,
  •   `name` varchar(255) DEFAULT NULL,
  •   `time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  •   `data` double(15,5) DEFAULT '-601.00000',
  •   PRIMARY KEY (`Id`,`time`),
  •   UNIQUE KEY `unique` (`name`,`time`)
  •   )

  •   CREATE TABLE `vardata_compute` (
  •   `Id` int(11) NOT NULL AUTO_INCREMENT,
  •   `name` varchar(255) DEFAULT NULL,
  •   `time` datetime DEFAULT NULL,
  •   `data` double(15,5) DEFAULT NULL,
  •   PRIMARY KEY (`Id`)
  •   )
  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   DROP TRIGGER IF EXISTS trigger_insert_59data;
  •   CREATE TRIGGER trigger_insert_59data
  •   AFTER INSERT
  •   ON vardata
  •   FOR EACH ROW
  •   BEGIN
  •   DECLARE time_59 DateTime;
  •   SET time_59 = NEW.time-INTERVAL 1 SECOND;
  •   IF MINUTE(NEW.time)=0 AND SECOND(NEW.time)=0 THEN
  •   INSERT INTO vardata_compute SET name=NEW.name,time=time_59,data=NEW.data;
  •   END IF;
  •   END;

  •   DROP TRIGGER IF EXISTS trigger_delete_59data;
  •   CREATE TRIGGER trigger_delete_59data
  •   AFTER DELETE
  •   ON vardata
  •   FOR EACH ROW
  •   BEGIN
  •   DECLARE time_59 DateTime;
  •   SET time_59 = OLD.time-INTERVAL 1 SECOND;
  •   IF MINUTE(OLD.time)=0 AND SECOND(OLD.time)=0 THEN
  •   DELETE FROM vardata_compute WHERE time=time_59 AND name=old.name;
  •   END IF;
  •   END;

  •   DROP TRIGGER IF EXISTS trigger_update_59data;
  •   CREATE TRIGGER trigger_update_59data
  •   AFTER UPDATE
  •   ON vardata
  •   FOR EACH ROW
  •   BEGIN
  •   DECLARE time_59 DateTime;
  •   SET time_59 = NEW.time-INTERVAL 1 SECOND;
  •   IF MINUTE(NEW.time)=0 AND SECOND(NEW.time)=0 THEN
  •   UPDATE vardata_compute SET data=NEW.data WHERE time=time_59 AND name=NEW.name;
  •   END IF;
  •   END;
9.mysql中大幅度提高性能方案———分区表  工作中仍然是海量数据出现的情况.每年大概会有几亿条记录.而且数据的时效性比较强.但历史数据仍然要求保留.这个时候经过分析和研究,最终决定通过时间字段进行分区.下面是分区表的创建代码.读者门在插入了不同年份时间段以后,可以时间字段为条件进行查询,可以看到数据库扫描过的区段.
  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   CREATE TABLE part_data
  •   (c1 int default NULL,
  •   c2 varchar(30) default NULL,
  •   c3 date default NULL)
  •   partition by range (to_days(c3))
  •   (PARTITION p0 VALUES LESS THAN (to_days('1995-01-01')),
  •   PARTITION p1 VALUES LESS THAN (to_days('1996-01-01')) ,
  •   PARTITION p2 VALUES LESS THAN (to_days('1997-01-01')) ,
  •   PARTITION p3 VALUES LESS THAN (to_days('1998-01-01')) ,
  •   PARTITION p4 VALUES LESS THAN (to_days('1999-01-01')) ,
  •   PARTITION p5 VALUES LESS THAN (to_days('2000-01-01')) ,
  •   PARTITION p6 VALUES LESS THAN (to_days('2001-01-01')) ,
  •   PARTITION p7 VALUES LESS THAN (to_days('2002-01-01')) ,
  •   PARTITION p8 VALUES LESS THAN (to_days('2003-01-01')) ,
  •   PARTITION p9 VALUES LESS THAN (to_days('2004-01-01')) ,
  •   PARTITION p10 VALUES LESS THAN (to_days('2010-01-01')),
  •   PARTITION p11 VALUES LESS THAN MAXVALUE );
  分区查询,可以查看扫描过的区段.当然要加上where子句,以c3时间为条件进行检索.若不使用时间字段,分区将失去作用.
  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   explain partitions select * from part_data\G
  10.mysql中海量数据统计处理,模拟物化视图
  一 物化视图
  物化视图,它是用于预先计算并保存表连接或聚集等耗时较多的操作的结果,这样,在执行查询时,就可以避免进行这些耗时的操作,而从快速的得到结果。
  只有大型数据库oracle10g,db2才支持这个功能,而MySQL5.1暂时还没有这个功能。本人通过事件调度和存储过程模拟了物化视图。下面大家一起来讨论吧。^-^
  二 准备知识
  1)存储过程:玩过数据库的人,都知道他是啥~,~
  2)事件调度:在MySQL5.1开始才有的新功能。说白了就是个定时器。跟java里的timer差不多。
  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   show processlist; --这个命令能是查看线程,如果启动了时间调度器,则会多个event_scheduler
  •   set global event_scheduler = on; --启动时间调度器,关闭就不用我说了吧,off就可以了
  •   show processlist\G;--查看线程,是不是多了个 User: event_scheduler

  •   --如果想启动单个事件,则执行下面命令
  •   ALTER EVENT `myEvent`
  •   ON COMPLETION PRESERVE
  •   ENABLE;
  •   --关闭
  •   ALTER EVENT `myEvent`
  •   ON COMPLETION PRESERVE
  •   DISABLE;
  mysql默认不会启动event,所以需要修改你的my.ini或my.cnf[mysqld]的下面加入如下行
  event_scheduler=1
  三 模拟物化视图
  1)先建个基表吧。
  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   CREATE TABLE `user` (
  •   `Id` int(11) NOT NULL AUTO_INCREMENT,
  •   `name` varchar(255) DEFAULT NULL,
  •   `age` int(11) DEFAULT NULL,
  •   PRIMARY KEY (`Id`)
  •   );
  2)设计视图
  我想查询所有18岁员工的数量。
  很简单,select count(*) from user where age=18;
  如果是传统概念的视图,在MySQL中,每次访问视图的时候,他都会创建个临时表,然后执行一次。在海量数据的情况下,这样的效率是非常低的。而物化视图,则他会定时去刷新这个临时表,而不是你在用的时候才会去刷新。并且物化视图的"临时表"是一直存在的。所以效率高出非常多。拿空间换时间^-^
  3)创建"物化视图"的表
  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   CREATE TABLE `user_view` (
  •   `Id` int(11) NOT NULL AUTO_INCREMENT,
  •   `c` int(11) DEFAULT NULL,
  •   PRIMARY KEY (`Id`)
  •   );
  4)设计存储过程
  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   CREATE PROCEDURE demoSp()
  •   BEGIN
  •   DECLARE z INT;
  •   SELECT COUNT(*) INTO z FROM user;
  •   delete from user_view;
  •   insert into user_view(c) values(z);
  •   END;
  5)设计调度并执行,为了使实验明显,我就把调度设置成5秒一次吧。周期可以自己调节。
  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   CREATE EVENT `myEvent`
  •   ON SCHEDULE EVERY 5 SECOND
  •   ON COMPLETION PRESERVE
  •   DO call demoSp();
  四 总结
  上面的实现,可能不太明显,但在海量数据处理的时候进行统计,性能有明显的提升。大家做实验的时候,可以增加一个insert语句,方便观察。在更新数据的时候,如果数据量大,则需要按下面步骤来处理
  1)delete 1条记录
  2)insert 1条记录
  3)提交
  如果一次性把数据全部删除,在查询的时候,有可能会出现空表的现象。而且会影响统计使用。
  通过利用这个事件调度,定时备份的事情也同时解决了.
  建议大家配合表分区,索引同时使用,这样可以提高性能.
  未完成:在更新表的时候,需要采用某种算法来执行,这样才能提高性能,而不是单纯的删除再插入.
  11.mysql中按月统计数据
  表finance有俩个字段如下
  date date
  money double(15,2)
  下面需要对表finance的2010年财务数据,按月进行统计
  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   select DATE_FORMAT(date,'%Y-%m') as month,sum(money) as money
  •   from finance
  •   where DATE_FORMAT(date,'%Y')=2010
  •   group by month
  •   order by month
  下面是按周统计
  查看MySQL的manual
  %X Year for the week where Sunday is the first day of the week, numeric, four digits; used with %V
  %x Year for the week, where Monday is the first day of the week, numeric, four digits; used with %v
  其中
  1如果周一为一周的第一天,则(小写) DATE_FORMAT(date,'%x %v')
  2如果周日为一周的第一天,则(大写) DATE_FORMAT(date,'%X %V')
  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   select DATE_FORMAT(date,'%x年-第%v周') as week,sum(money) as money
  •   from finance_base
  •   where DATE_FORMAT(date,'%Y')=2010
  •   group by week
  12.mysql中数据的重复判断
  工作中的实际应用.在采集数据的时候,要求数据采集以后,不能重复.同时也要求有多个实例同时运转,保证数据采集的连续性.因此总结了一下,做成了如下的小试验.核心代码如下:
  表结构:只有3个字段
  id,name,password
  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   CREATE TABLE `tt` (
  •   `Id` int(11) NOT NULL AUTO_INCREMENT,
  •   `name` varchar(255) DEFAULT NULL,
  •   `password` varchar(255) DEFAULT NULL,
  •   PRIMARY KEY (`Id`)
  •   ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  sql语句
  1)推荐
  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   insert ignore into tt(name,password) values('phl','123')
  2)不推荐,因为insert的时候select,会锁定select的表
  Sql代码  http://phl.iteye.com/images/icon_star.png

  •   insert into tt(name,password) select 'phl','123' from dual where not exists(select * from tt where name='phl' and password='123')
  这个SQL语句的含义是,如果插入的数据 name='phl',password='123'不存在,则执行插入;
  补充:
  方法1里面,之所以没有过滤。是因为没有建立name与password的联合主建;
  本文出自http://blog.csdn.net/feihong247/article/details/7847722


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-619600-1-1.html 上篇帖子: mysql日常维护 下篇帖子: Mysql基础系列(一)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表