正在加载...
分页: 7/13 第一页 上页 2 3 4 5 6 7 8 9 10 11 下页 最后页 [ 显示模式: 摘要 | 列表 ]

mysql 删除表中的重复记录

[ 2009/07/31 20:53 | by selboo ]
      MySQL中漏掉了40%左右的数据,寻找这个错误的代价是花了三天,将所有的代码重新检查了一遍,由于代码不是我写的,看得晕头转向,上苍保佑,我还不算太笨,最终找到了原因,不过接着就碰到另外一个问题,找回的数据中存在重复,而且在无法在重复的健上建立唯一,于是我想了一个最笨的方法

SELECT * FROM sub_new   WHERE email  IN (
SELECT  email  FROM sub_new
GROUP  BY  email  HAVING  count(email) > 1
)


这种算法是最傻也是最没出息的算法,在数量在1W的时候还可以接受,到10W就要两分钟了,到50W就死在那里了,所以告诫那些跟我一样天资不算聪明的人,数据量比较大的时候千万别用这种方法,这种类似冒泡排序的算法复杂度是O(n^2),如果你有10W条记录,你自己乘一下吧  

接着又想了另外一个方法,虽然机械了点,不过效率非常之高,分三步走:

CREATE   TABLE   tmp   AS   SELECT   *   FROM   youtable
  GROUP   BY   name

DROP   TABLE   youtable
ALTER   TABLE   tmp   RENAME   youtable


10W条记录,在第一步处理师大约为4秒,50w条记录时为19秒左右,再往上就没测了

后面两条语句纯粹是体力活,如果你用的是phpadmin,点点鼠标就可以搞定

Tags:
从http://hackmysql.com/mysqlsla下载mysqlsla,当前最新版为:2.03

tar zxvf mysqlsla-2.03.tar.gz
cp mysqlsla-2.03/bin/mysqlsla /usr/local/bin
如果提示“Can’t locate DBI.pm”,执行以下命令

yum install perl-DBI perl-DBD-MySQL -y
这时就可以使用mysqlsla了,用法如下

mysqlsla -lt slow slow.log

点击在新窗口中浏览此图片

整体来说, 功能非常强大. 数据报表,非常有利于分析慢查询的原因, 包括执行频率, 数据量, 查询消耗等.
格式说明如下:
总查询次数 (queries total), 去重后的sql数量 (unique)
输出报表的内容排序(sorted by)
最重大的慢sql统计信息, 包括 平均执
Tags: , ,
环境:
Windows XP
PHP Version 5.2.9
MySQL Server 5.1

第一步、创建一个表date_test(非定长、int时间)

CREATE TABLE `test`.`date_test` (
`id` INT NOT NULL AUTO_INCREMENT ,
`start_time` INT NOT NULL ,
`some_content` VARCHAR( 255 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = InnoDB;

第二步、创建第二个表date_test2(定长、int时间)

CREATE TABLE `test`.`date_test2` (
`id` INT NOT NULL AUTO_INCREMENT ,
`start_time` INT NOT NULL ,
`some_content` CHAR( 255 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = InnoDB;

第三步、创建第三个表date_test3(varchar、datetime时间)

CREATE TABLE `test`.`date_test3` (
`id` INT NOT NULL AUTO_INCREMENT ,
`start_time` DATETIME NOT NULL ,
`some_content` VARCHAR( 255 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = InnoDB;

第四步、创建第四个表date_test3(char、datetime时间)

CREATE TABLE `test`.`date_test4` (
`id` INT NOT NULL AUTO_INCREMENT ,
`start_time` DATETIME NOT NULL ,
`some_content` CHAR( 255 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = InnoDB;

ok,现在我们开始做测试,环境是php,先向各个表插入一百万条数据。插入的时候分200次,每次进库5000条。

表一执行记录:页面运行时间: 26.5997889042 秒,插入的时候发现一个有趣的现象:SELECT count( id ) FROM `date_test` WHERE 1 的结果是100w,而直接select * from `date_test`却是1,000,374条结果。(后来看到这是一个可能接近的值,请参看MySQL FAQ 3.11)。
表二执行记录:页面运行时间: 62.3908278942 秒,这次记录是1,000,066条。
表三执行记录:页面运行时间: 30.2576560974 秒,这次的是1,000,224条。
表四执行记录:页面运行时间: 67.5393900871 秒,这次的是:1,000,073条。

现在把四个表的start_time字段一一加上索引。

测试四个表的更新,分别update 100条记录,并记录时间:
表一:页面运行时间: 2.62180089951 秒(非定长,int时间)
表二:页面运行时间: 2.5475358963 秒(定长,int时间)
表三:页面运行时间: 2.45077300072 秒(varchar,datetime时间)
表四:页面运行时间: 2.82798409462 秒(char,datetime时间)

测试四个表的读取,分别select 100条随机记录,以主键id为条件查询,并记录时间:
表一:页面运行时间: 0.382651090622 秒(非定长,int时间)
表二:页面运行时间: 0.542181015015 秒(定长,int时间)
表三:页面运行时间: 0.334048032761 秒(varchar,datetime时间)
表四:页面运行时间: 0.506206989288 秒(char,datetime时间)

测试四个表的读取,分别select 10条随机记录,以star_time为条件查询,并记录时间:
表一:页面运行时间: 30.1972880363 秒(非定长,int时间)
表二:页面运行时间: 65.1926910877 秒(定长,int时间)
表三:页面运行时间: 39.7210869789 秒(varchar,datetime时间)
表四:页面运行时间: 70.4632740021 秒(char,datetime时间)

因为量比较小,所以我们默认即使是微小的变化,也是有意义的。

结论:

大数据量下,如果存在大量的select * from table where 时间>XX这样的查询,在MySQL5.1时使用int换datetime是有意义的。

MySQL 测试小脚本

[ 2009/07/06 03:39 | by selboo ]
经常有人在msn上问我,如何做一个简单的测试。如insert数据到表中的行为。
比较myisam和innodb等。
在这里将自己写的一个小脚本放上来,希望你们停止骚扰我的msn
首先创建一个库
create database mysqlsystems
use mysqlsystems;
创建两个表 - innodb的和myisam的
CREATE TABLE `myisam` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(50) default NULL,
`post` text,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `innodb` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(50) default NULL,
`post` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
这样叫创建了两个表,innodb和myisam。
创建可插入数据的 存储过程
delimiter @
create procedure insert_isam(in item integer)
begin
declare counter int;
set counter = item;
while counter >= 1 do
insert into myisam values(counter,concat('mysqlsystems.com',counter),repeat('bla',10));
set counter = counter - 1;
end while;
end
@

create procedure insert_innodb(in item integer)
begin
declare counter int;
set counter = item;
while counter >= 1 do
insert into innodb values(counter,concat('mysqlsystems.com',counter),repeat('bla',10));
set counter = counter - 1;
end while;
end
@
delimiter ;
好了,
运行吧,
你要插入100条到innodb?         执行call insert_innodb(100)
插入1000000到myisam?          call insert_myisam(1000000)
记得再一次插入新的内容时,要清空你的表,delete from ,或者truncate 。
插入10亿条?
Tags:
近日笔者工作中遇到MYSQL数据从高版本导入低版本的问题.这样的问题一般都是高低版本字符集的设置不同.按照以往惯例是把数据用mysqldump命令导出数据后,使用文件编辑器(editplus)修改相应的"DEFAULT CHARSET=gb2312"部分,即可顺利导入低版本的MySQL.但当你遇到大量数据(百万级)时,这种方式就显示得杯水车薪了!那么么办呢?现本人就把自己工作中遇到有关MYSQL数据从高版本导入低版本的解决办法总结一下.

方法一:(适用于当导出的数据量不大时)

step 1:使用mysqldump命令从源服务器导出成SQL文本
mysqldump -hsrc_dbserver -uroot -p testdb > testdb.sql
step 2:使用文本编辑器如:editplus,打开testdb.sql,打到需要修改的内容,如:DEFAULT CHARSET=gb2312,修改成与目标服务器相对应的字符集.保存.
step 3:使用mysql命令将改好后的SQL文本导入目标服务器.OK!
mysql -hdest_dbserver -uroot -p testdb < testdb.sql

方法二:(适用于当导出的数据量很大时,如万级,百万级数据)

step 1:在mysql命令模式下,使用show variables 命令查看一下目标服务器的字符集设置情况和MYSQL版本
step 2:使用如下命令:
mysqldump --compatible=mysql323 -hsrc_dbserver -uroot -p --default-character-set=latin1 testdb > testdb.sql

其中,--compatible=mysql323 是指目标服务器的版本,--default-character-set=latin1 是指目标服务器的字符集设置
step 3:使用mysql命令将导出的SQL文本导入目标服务器.OK!大功告成!
mysql -hdest_dbserver -uroot -p testdb < testdb.sql


快速替换
sed -i 's#DEFAULT CHARSET=gb2312# #' 文件名
Tags:
分页: 7/13 第一页 上页 2 3 4 5 6 7 8 9 10 11 下页 最后页 [ 显示模式: 摘要 | 列表 ]