Skip to content

Commit

Permalink
Vyřešení zpomalení v MySQL kvůli vysokým offsetům podle https://stack…
Browse files Browse the repository at this point in the history
  • Loading branch information
michallohnisky committed Dec 15, 2020
1 parent 3a4c6c6 commit e7034dc
Showing 1 changed file with 89 additions and 5 deletions.
94 changes: 89 additions & 5 deletions src/QueryBuilderFetcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,107 @@

namespace ADT\BulkFetcher;

use App\Utils;
use Kdyby\Doctrine\Dql\InlineParamsBuilder;
use Kdyby\Doctrine\NativeQueryBuilder;

/**
* Vyřešení zpomalení v MySQL kvůli vysokým offsetům podle https://stackoverflow.com/a/16935313/4837606
*/
class QueryBuilderFetcher extends AbstractFetcher {

/** @var \Doctrine\ORM\QueryBuilder */
/** @var NativeQueryBuilder|InlineParamsBuilder */
protected $qb;

public function __construct($qb, $batch = 100) {
/** @var array */
protected $lastRowData = NULL;

/** @var string */
protected $entityIdentifierColumn = NULL;

/** @var array */
protected $queryHints = [];

public function setHint($name, $value)
{
$this->queryHints[$name] = $value;
return $this;
}

/**
* QueryBuilderFetcher constructor.
* @param int $qb
* @param int $batch
* @param string $entityIdentifierColumn
*/
public function __construct($qb, $batch = 100, $entityIdentifierColumn = 'e.id') {
parent::__construct($batch);

$this->qb = $qb;
$this->entityIdentifierColumn = $entityIdentifierColumn;

$this->lastRowData = [
$this->entityIdentifierColumn => 0,
];

$this->qb->andWhere("{$this->entityIdentifierColumn} > :".static::param($this->entityIdentifierColumn));

$this->qb->addOrderBy("{$this->entityIdentifierColumn}", 'ASC');
}

protected function loadNewData() {
return $this->qb
->getQuery()
->setFirstResult($this->offset)

foreach ($this->lastRowData as $columnName => $value) {
$this->qb->setParameter(static::param($columnName), $value);
}

$query = $this->qb
->getQuery();

foreach ($this->queryHints as $name => $value) {
$query->setHint($name, $value);
}

$data = $query
->setFirstResult(0)
->setMaxResults($this->limit)
->getResult();

if (!count($data)) {
return $data;
}

$lastRow = $data[count($data)-1];


if (!is_object($lastRow)) {
// Doctrine vrací objekt na indexu 0
$lastRow = $lastRow[0]; // TODO: možnost nastavit si callback, který vrátí atribut (viz dále)
}

foreach (array_keys($this->lastRowData) as $columnName) {
// TODO: možnost nastavit si callback, který vrátí atribut, protože to nemusí být pole objektů

$rootEntityAlias = substr($this->entityIdentifierColumn, 0, strpos($this->entityIdentifierColumn, '.')); // "e.id" -> "e"
$propertyName = str_replace(
'.',
'->',
strpos($columnName, $rootEntityAlias.'.') === 0
? substr($columnName, strpos($columnName, '.') + 1) // "e.column1" -> "column1"
: $columnName
);

$this->lastRowData[$columnName] = Utils::accessNestedObjectPropertyByString($propertyName, $lastRow);
}


return $data;
}

protected static function param($param)
{
// TODO: možnost nastavit si název parametru, aby náhodou nekolidoval
return 'QueryBuilderFetcher_' . str_replace('.', '__', $param);
}

}
Expand Down

0 comments on commit e7034dc

Please sign in to comment.