2013-06-21 21 views
6

ZF2 Paginator'ı büyük (bir arama filtresi olmayan en kötü durumda yaklaşık 10 milyon) kayıt kümesinde kullanmaya çalışıyorum. Tablolarım InnoDB biçimindedir, anladığım kadarıyla meta verilerde belirli bir sayı tutmayınız.Count için Abysmal Performansı() InnoDB Tabloları üzerinde ZF2 Paginator kullanarak

Zend \ Paginator \ Adapter \ DbSelect sınıfını genişletebileceğimi ve başka bir tabloda el ile depoladığım sayım verilerini kullanan kendi count() yöntemimi uygulayabileceğimin farkındayım, ancak sayıları nasıl depolayacağımı bilmiyorum. Yapılabilecek aramaların tüm olası permütasyonları. Ben performans MyISAM üzerinde ne olurdu emin değilim

SELECT 
    COUNT(1) AS `c` 
FROM 
    (
     SELECT 
      `contacts`.`id` AS `id`, 
      `contacts`.`firstname` AS `firstname`, 
      `contacts`.`middlename` AS `middlename`, 
      `contacts`.`lastname` AS `lastname`, 
      `contacts`.`gender` AS `gender` 
     FROM 
      `contacts` 
     WHERE 
      `contacts`.`trash` = '0' 
    ) AS `original_select` 

:

İşte
<?php 
public function count() 
{ 
    if ($this->rowCount !== null) { 
     return $this->rowCount; 
    } 

    $select = clone $this->select; 
    $select->reset(Select::LIMIT); 
    $select->reset(Select::OFFSET); 
    $select->reset(Select::ORDER); 

    $countSelect = new Select; 
    $countSelect->columns(array('c' => new Expression('COUNT(1)'))); 
    $countSelect->from(array('original_select' => $select)); 

    $statement = $this->sql->prepareStatementForSqlObject($countSelect); 
    $result = $statement->execute(); 
    $row  = $result->current(); 

    $this->rowCount = $row['c']; 

    return $this->rowCount; 
} 
?> 

çok basit bir örnek yöntemi benim için üretir sorgudur:

varsayılan ZF2 DbSelect adapter bu yöntemi kullanır Tablolar, ancak bu, çalıştığı Amazon RDS (25GB, db.m1.small) örneğinin tüm boş alanlarını tüketmesi nedeniyle başarısız oluyor. Karşılaştırma olarak, sadece iç (orijinal) sorguyu çalıştırarak, 100 saniyede tamamlar (kesinlikle iyi değil) ve 7.39 milyon kayıt döndürür. İşte

iç sorgudan AÇIKLAMAK (bir de, çünkü RDS sunucusunda disk alanının ölür sayımı biri üzerinde AÇIKLAYINIZ) gelir: Bu daha iyi ayarlamak için yapılabilecek bir şey

 
+----+-------------+----------+------+---------------+-------+---------+-------+---------+-------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | 
+----+-------------+----------+------+---------------+-------+---------+-------+---------+-------+ 
| 1 | SIMPLE  | contacts | ref | trash   | trash | 1  | const | 3441317 |  | 
+----+-------------+----------+------+---------------+-------+---------+-------+---------+-------+ 
1 rows in set (0.04 sec) 

var mı? ZF2 Paginator'ın sayımları, InnoDB'nin bir şeyi yaptığı şekilde bir şekilde uyumsuz sayar mı? Veritabanındaki alanların çoğunda arama yapılmasına izin verirsek, diğer olası sorguların önbellek sayımları nasıl ele alınır? peşin

Teşekkürler ... bunun yerine bu sorguyu kullanırsanız

+0

Bu sorun, InnoDB'nin doğasında var, MyISAM, meta verilerindeki bir tablodaki satır sayısını izlediği için bu soruna sahip değil. Sadece bir veritabanı kullanıcı arayüzünde sorgu çimdik ve hangi etkiyi görmek için muhtemelen en iyisidir. : Bunun yerine COUNT (1) – Ruben

+0

** COUNT (1) ** Örneğin COUNT (id) deneyin ya mysql> select count (1) den ... kullanım endeksi (your_index) kullanarak belirli bir dizin kullanmak için MySQL söyleyebilirdi 15 dakika 36 saniye; ** COUNT (id) **: 18 dk 8.83sec – jcq

cevap

0

:

SELECT c from 
( 
    SELECT COUNT(1) AS c 
    from contacts 
    where trash = '0' 
) AS original_select 
2

Orijinal sorgudan seçme gerekmez - bu hafıza/diskspace tüketir! Bunun yanı sıra

SELECT count(1) AS `c` 
FROM (
    SELECT 1 
    FROM `contacts` 
    WHERE `trash` = 0 
) AS `original_select` 

:

  • çöp sadece bir mantıksal değerdir varsayarsak, bu bir boolean değil null sütun yapıp int arayabilir veya boolean/yanlış doğrudur

    ALTER TABLE `contacts` CHANGE `trash` `trash` TINYINT(1) NOT NULL 
    
  • Çöp kutusu sütununu

    ALTER TABLE `contacts` ADD INDEX `TRASH` (`trash`) 
    
  • numaralı dizine eklediğinizden emin olun. Dahası

: mutlaka tam bir sayı gerektirmeyen geniş sonuç kümeleri

  • Sayfalandırma: Biz Sayfa başına 100 girdileri görüntüleniyor Say, bir 100000 tek sayfa N düğmelerini gerekmez. Bunun yerine, ofset ve limitinizi kullanarak sayfayı hesaplayın ve sadece örn. prev/sonraki 10 sayfa ve bazı "show next/prev 10 pages" düğmeleriyle birleştirin."kısa bir süre sayfasına giderek" olasılığını gerektiğinde

  • neden benzer bir şey elde etmek için DESC sipariş gibi bir şey kullanmayın.

  • gerçekten birisi 10m satırlar arasında paginate verecek bir durum var mı? Belki de kullanıcının ihtiyaç duyduğu şeyi bulmasına yardımcı olmak için gelişmiş filtreler sağlar.