mysql千万级数据怎么做优化
function insert(){ global $m; if (!isset($_REQUEST['strs']) || !isset($_REQUEST['type']) || !isset($_REQUEST['hash'])){ echo 'param error'; return; } //strs为所有字符串 $poststr = $_REQUEST['strs']; $xstrs = json_decode(stripslashes($poststr), true); $type = $_REQUEST['type']; $hash = $_REQUEST['hash']; if (count($xstrs) <= 0){ $msg = 'str error'; DsLog::errLog($msg.$poststr); echo $msg; return; } if ($type == '0'){ $table = 'white'; } else if($type == '1'){ $table = 'black'; } else{ $msg = 'type error'; DsLog::errLog($msg); echo $msg; return; } $strs = array(); for($i = 0; $i < count($xstrs); $i++) { $strtmp = $xstrs[$i]; $strtmp = trim($strtmp); $strtmp = strtolower($strtmp); $strtmp = addslashes($strtmp); if (strlen($strtmp) > 256){ $strtmp = substr($strtmp, 0, 256); } if (strlen($strtmp) >= 7) { array_push($strs, $strtmp); } } //拼接所有字符串 $tmp = '("'.implode('","', $strs).'")'; //获取已存在的字符串 $sql = "select * from $table where str in $tmp"; $ret = mysql_query($sql, $m); if (!$ret){ $msg = 'exec error:'.mysql_error($m).','.$sql; DsLog::errLog($msg); echo $msg; return; } $exists = array(); $notexists = array(); $count = mysql_num_rows($ret); for ($i = 0; $i < $count; $i++) { $item = mysql_fetch_assoc($ret); if (!$item){ break; } array_push($exists, $item['str']); } for ($i = 0; $i < count($strs); $i++){ if (in_array($strs[$i], $exists)){ continue; } array_push($notexists, $strs[$i]); } for($i = 0; $i < count($exists); $i++) { $exists[$i] = addslashes($exists[$i]); } for($i = 0; $i < count($notexists); $i++) { $notexists[$i] = addslashes($notexists[$i]); } if (count($exists) > 0){ //更新已存在字符串的count字段 $tmp = '("'.implode('","', $exists).'")'; $time = date('YmdHi'); $sql = "update $table set count=count+1 where str in $tmp"; $ret = mysql_query($sql, $m); if (!$ret){ $msg = 'exec error:'.mysql_error($m).','.$sql; DsLog::errLog($msg); echo $msg; return; } //更新已存在字符串的upd字段 $sql = "update $table set upd='$time' where str in $tmp"; $ret = mysql_query($sql, $m); if (!$ret){ $msg = 'exec error:'.mysql_error($m).','.$sql; DsLog::errLog($msg); echo $msg; return; } } //插入新信息 if (count($notexists) > 0){ $time = date('YmdHi'); $sql = "insert ignore into $table (str,hash,count, upd) values"; for ($i = 0; $i < count($notexists); $i++){ $str = $notexists[$i]; $crc = sprintf("%u", crc32($str)); $sql .= "('$str','$crc','1', '$time'),"; } $sql = substr($sql, 0, strlen($sql) - 1); $ret = mysql_query($sql, $m); if (!$ret){ $msg = 'insert error:'.mysql_error($m).','.$sql; DsLog::errLog($msg); echo $msg; return; } } echo !!$ret; }
我现在要对字符串做统计,统计每个字符串的数量,就是类似一个map, 这符串:数量,当然,数据库顺便还保存了一下字符中的crc等信息
insert函数接收post过来的strs,这是一个字符串数组,每次post过来的字符串数量平均为1500
现在数据库里的记录1200W条,每一次insert花费的时间平均为20秒(经常出现30秒超时)
请问下各位,该怎么做优化,现在只是统计了很小一部分,预计统计完数据量大概在1-10亿条
回复讨论(解决方案)
对了,str字段做了唯一索引,其它字段没做,mysql为MyISAM
你能确定瓶颈是在数据库做 查询 和 修改 的3条语句上吗?
你说 每次post过来的字符串数量平均为1500
那是指 1500 的单词吗?就算不是(是串长度)那么以平均每个单词20个字符计算,也有75个单词
你的过滤条件是 str in $tmp (str in ('xxx','xxx'....))也就是对表中的每一条记录都要做 1500(75)次字符串比较,而命中率至多是1/1500(1/75)你认为这样做合适吗?
数据库的强项在于记录间的比较,而你却在做弱势的列间比较
你可以用传入的数据构造出一个临时表(每行一个单词),再去与主表关联操作。这样才能发挥数据库的优势
再有,你的连续 2 条 update 语句不能合并在一起吗?
你能确定瓶颈是在数据库做 查询 和 修改 的3条语句上吗?
你说 每次post过来的字符串数量平均为1500
那是指 1500 的单词吗?就算不是(是串长度)那么以平均每个单词20个字符计算,也有75个单词
你的过滤条件是 str in $tmp (str in ('xxx','xxx'....))也就是对表中的每一条记录都要做 1500(75)次字符串比较,而命中率至多是1/1500(1/75)你认为这样做合适吗?
数据库的强项在于记录间的比较,而你却在做弱势的列间比较
你可以用传入的数据构造出一个临时表(每行一个单词),再去与主表关联操作。这样才能发挥数据库的优势
再有,你的连续 2 条 update 语句不能合并在一起吗?
1500是指字符数,字符数应该在5W左右
你的意思是先把1500条记录insert到一个临时表tmp_table,然后
然后 select* from table inner join tmp_talbe on table.str = tmp_table.str 这样么?
你能确定瓶颈是在数据库做 查询 和 修改 的3条语句上吗?
你说 每次post过来的字符串数量平均为1500
那是指 1500 的单词吗?就算不是(是串长度)那么以平均每个单词20个字符计算,也有75个单词
你的过滤条件是 str in $tmp (str in ('xxx','xxx'....))也就是对表中的每一条记录都要做 1500(75)次字符串比较,而命中率至多是1/1500(1/75)你认为这样做合适吗?
数据库的强项在于记录间的比较,而你却在做弱势的列间比较
你可以用传入的数据构造出一个临时表(每行一个单词),再去与主表关联操作。这样才能发挥数据库的优势
再有,你的连续 2 条 update 语句不能合并在一起吗?
1500是字符串数,大概3W个字符
你的意思是把1500个字符中插入到临时表tmp里,然后再 select* from white inner join tmp on white.str=tmp.str 么?
我刚测了下
select* from white inner join tmp on white.str=tmp.str 执行时间10S
id select_type table type possible_keys key key_len ref rows Extra1 SIMPLE tmp index str str 770 NULL 2531 Using index1 SIMPLE white eq_ref str str 770 bayes.tmp.str 1
直接执行 select * from white where str in(''xxx','xxx'...) 执行时间9S
id select_type table type possible_keys key key_len ref rows Extra1 SIMPLE white range str str 770 NULL 2531 Using where
感觉效果差不多一样
1、mysql 有内存表,你并未使用
2、将两条 update 合并,应该能减少 10 秒
mysql_error这种库函数的效率也不高吧而且官方也不推荐,我几乎没有用过这种,我学PHP的时候,直接开始PDO的。
还有,你用了in这个关键字,好像它是不走索引的吧。
感觉效果差不多一样
应该是你测试环境的问题吧,联表查询大多数情况下是要比in快的
你测的结果差不多可能是如下原因
1.查询表的数据没有达到一定量
2.两种查询方式查出的结果集不同
3.查询字段未加索引或加的不对
4.被其他索引过多而影响
5.其他原因
我认为比较明显的就是第2个原因
你联表查时没有指定查询字段,联表出的字段肯定要比不连表的要多
还有联表查询会有一对多的情况,那样一条记录就会变成多条的,要加group by

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

JWT是一种基于JSON的开放标准,用于在各方之间安全地传输信息,主要用于身份验证和信息交换。1.JWT由Header、Payload和Signature三部分组成。2.JWT的工作原理包括生成JWT、验证JWT和解析Payload三个步骤。3.在PHP中使用JWT进行身份验证时,可以生成和验证JWT,并在高级用法中包含用户角色和权限信息。4.常见错误包括签名验证失败、令牌过期和Payload过大,调试技巧包括使用调试工具和日志记录。5.性能优化和最佳实践包括使用合适的签名算法、合理设置有效期、

会话劫持可以通过以下步骤实现:1.获取会话ID,2.使用会话ID,3.保持会话活跃。在PHP中防范会话劫持的方法包括:1.使用session_regenerate_id()函数重新生成会话ID,2.通过数据库存储会话数据,3.确保所有会话数据通过HTTPS传输。

SOLID原则在PHP开发中的应用包括:1.单一职责原则(SRP):每个类只负责一个功能。2.开闭原则(OCP):通过扩展而非修改实现变化。3.里氏替换原则(LSP):子类可替换基类而不影响程序正确性。4.接口隔离原则(ISP):使用细粒度接口避免依赖不使用的方法。5.依赖倒置原则(DIP):高低层次模块都依赖于抽象,通过依赖注入实现。

如何在系统重启后自动设置unixsocket的权限每次系统重启后,我们都需要执行以下命令来修改unixsocket的权限:sudo...

在PHPStorm中如何进行CLI模式的调试?在使用PHPStorm进行开发时,有时我们需要在命令行界面(CLI)模式下调试PHP�...

静态绑定(static::)在PHP中实现晚期静态绑定(LSB),允许在静态上下文中引用调用类而非定义类。1)解析过程在运行时进行,2)在继承关系中向上查找调用类,3)可能带来性能开销。

使用PHP的cURL库发送JSON数据在PHP开发中,经常需要与外部API进行交互,其中一种常见的方式是使用cURL库发送POST�...
