下面是ma方法(Symfony,Doctrine),用於刪除其中的id不存在於其他表中,其中包含來自多個不同類型的id的列表。 (正好6,但重要的只是瞭解系統的結構)刪除巨大表中不存在的大型子集中的記錄
而且一切工作都很完美,除非該方法調用包含約300000條記錄和輔助表('oId')具有類似數量的實體參數的記錄。 (所以該方法應該只刪除我解釋的幾條記錄)當早些時候所有的作品(一個記錄數到50000以下的表),在這裏我遇到了從數據庫的問題:
SQLSTATE [HY000]:一般錯誤:1205鎖超時等待超時;嘗試重新啓動交易
此錯誤從未出現與以前的實體。 我不知道是什麼問題,因爲記錄的數量只有十倍大,所以當這些查詢通過幾秒鐘執行,爲什麼我看不到結果後例如。 20秒。? 背景是什麼,這樣的錯誤被拋出?
我甚至重建我的方法來做循環中的任務,就像在一些關於如何從表格中刪除大量記錄的答案中所說的那樣。此外,我將限制減少到1000條記錄,一切運行正常,除非它開始使用前面描述的實體。
這是整個方法。
只有一個更多的小解釋。不要害怕sql注入。 $ typeId和$ borderId來自數據庫,不是來自用戶。
/**
* Deletes records from given entity which are not exists in imported csv file.
*
* @param string $entity
* @param integer $typeId
* @param int $borderId Additional condition. Eg. 5 means, none of entities below id of value 5 will be delted (id < 5)
*/
public function removeNonExistent($entity, $typeId, $borderId = null)
{
$subQueryQb = $this->repository->createQueryBuilder('oId');
$subQueryQb->select('oId.originalId')
->andWhere('oId.type = '.$typeId)
//->andWhere('oId.originalId = e.originalId')
//Uncomment to have subquery of EXIST rather the IN()
;
$qb = $this->em->createQueryBuilder();
$qb->select('min(e.id) as minId, max(e.id) as maxId, count(e.id) as countId');
$qb->from($entity, 'e');
$tableData = $qb->getQuery()->getArrayResult();
$queries = 0;
$limit = 1000;
$id = $tableData[0]['minId'];
while ($id < $tableData[0]['maxId']) {
$deleteQb = $this->em->createQueryBuilder();
$deleteQb->delete()
->from($entity, 'e')
->andWhere('e.id BETWEEN '.$id.' AND '.($id + $limit - 1))
->andWhere($deleteQb->expr()->notIn('e.originalId', $subQueryQb→getDQL())) //Comment to use subquery as EXIST rather than IN()
//->andWhere($deleteQb->expr()->not($deleteQb->expr()->exists($subQueryQb->getDQL())))
//Uncomment to use subquery as EXIST rather than IN()
;
if ($borderId !== null) {
$deleteQb->andWhere('e.id > '.$borderId);
}
$qResult = $deleteQb->getQuery()->getResult();
$this->em->flush($entity);
$queries++;
echo $queries.'# delete query executed. Rows deleted: '.$qResult."\n";
$id += $limit;
if ($tableData[0]['countId'] < $limit) {
break;
}
}
echo $queries.' delete queries executed.'."\n";
}
任何人都可以幫忙嗎?任何線索我都會很高興。
在迭代之間使用睡眠 – mcklayin
難道這很簡單嗎?現在我無法檢查,但只要我可以,我會檢查它。我相信就是這樣。提前致謝! –
請向我們展示生成的SQL。不要使用'IN(SELECT ...)'它可能比'LEFT JOIN'慢。使用'autocommit',而不是一個大事務。 –