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 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Alipay PHP ...

JWT는 주로 신분증 인증 및 정보 교환을 위해 당사자간에 정보를 안전하게 전송하는 데 사용되는 JSON을 기반으로 한 개방형 표준입니다. 1. JWT는 헤더, 페이로드 및 서명의 세 부분으로 구성됩니다. 2. JWT의 작업 원칙에는 세 가지 단계가 포함됩니다. JWT 생성, JWT 확인 및 Parsing Payload. 3. PHP에서 인증에 JWT를 사용하면 JWT를 생성하고 확인할 수 있으며 사용자 역할 및 권한 정보가 고급 사용에 포함될 수 있습니다. 4. 일반적인 오류에는 서명 검증 실패, 토큰 만료 및 대형 페이로드가 포함됩니다. 디버깅 기술에는 디버깅 도구 및 로깅 사용이 포함됩니다. 5. 성능 최적화 및 모범 사례에는 적절한 시그니처 알고리즘 사용, 타당성 기간 설정 합리적,

세션 납치는 다음 단계를 통해 달성 할 수 있습니다. 1. 세션 ID를 얻으십시오. 2. 세션 ID 사용, 3. 세션을 활성 상태로 유지하십시오. PHP에서 세션 납치를 방지하는 방법에는 다음이 포함됩니다. 1. 세션 _regenerate_id () 함수를 사용하여 세션 ID를 재생산합니다. 2. 데이터베이스를 통해 세션 데이터를 저장하십시오.

PHP 개발에서 견고한 원칙의 적용에는 다음이 포함됩니다. 1. 단일 책임 원칙 (SRP) : 각 클래스는 하나의 기능 만 담당합니다. 2. Open and Close Principle (OCP) : 변경은 수정보다는 확장을 통해 달성됩니다. 3. Lisch의 대체 원칙 (LSP) : 서브 클래스는 프로그램 정확도에 영향을 미치지 않고 기본 클래스를 대체 할 수 있습니다. 4. 인터페이스 격리 원리 (ISP) : 의존성 및 사용되지 않은 방법을 피하기 위해 세밀한 인터페이스를 사용하십시오. 5. 의존성 반전 원리 (DIP) : 높고 낮은 수준의 모듈은 추상화에 의존하며 종속성 주입을 통해 구현됩니다.

시스템이 다시 시작된 후 UnixSocket의 권한을 자동으로 설정하는 방법. 시스템이 다시 시작될 때마다 UnixSocket의 권한을 수정하려면 다음 명령을 실행해야합니다.

phpstorm에서 CLI 모드를 디버그하는 방법은 무엇입니까? PHPStorm으로 개발할 때 때때로 CLI (Command Line Interface) 모드에서 PHP를 디버그해야합니다 ...

정적 바인딩 (정적 : :)는 PHP에서 늦은 정적 바인딩 (LSB)을 구현하여 클래스를 정의하는 대신 정적 컨텍스트에서 호출 클래스를 참조 할 수 있습니다. 1) 구문 분석 프로세스는 런타임에 수행됩니다. 2) 상속 관계에서 통화 클래스를 찾아보십시오. 3) 성능 오버 헤드를 가져올 수 있습니다.

PHP 개발에서 PHP의 CURL 라이브러리를 사용하여 JSON 데이터를 보내면 종종 외부 API와 상호 작용해야합니다. 일반적인 방법 중 하나는 컬 라이브러리를 사용하여 게시물을 보내는 것입니다 ...
