2016-01-11 5 views
0

Основываясь на http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/ Следующий SQL-запрос возвращает массив городов ближайший к $lat/$lon парам в данных $radius. Я добавил еще join-заявку (c.) для отображения code3l -колона из таблицы Country для каждого города. В целом это утверждение занимает около 1.2sek из-за количество 3Mio записейSQL COUNT (*) а РЕГИСТРИРУЙТЕСЬ-заявление вместо COUNT (*) внутри вложенного Select-заявления для лучшей производительности

SELECT population, AccentCity, Country, code3l, name, City, Region, 
     Latitude, Longitude, distance, id   
     FROM (
     SELECT z.population,z.id, 
       z.AccentCity,z.Country, z.City, z.Region, 
       z.Latitude, z.Longitude, 
       c.name, c.code3l, 
       p.radius, 
       p.distance_unit 
         * DEGREES(ACOS(COS(RADIANS(p.latpoint)) 
         * COS(RADIANS(z.latitude)) 
         * COS(RADIANS(p.longpoint - z.longitude)) 
         + SIN(RADIANS(p.latpoint)) 
         * SIN(RADIANS(z.latitude)))) AS distance 

      FROM worldpopulation AS z 
      JOIN ( 
       SELECT '.$lat.' AS latpoint, '.$lon.' AS longpoint, 
         '.$radius.' AS radius,  111.045 AS distance_unit 
      ) AS p ON 1=1 

      JOIN ( 
       SELECT * FROM countries 
      ) AS c ON c.code2l = z.Country 


      WHERE 
      z.population IS NOT NULL 

      AND z.latitude 
      BETWEEN p.latpoint - (p.radius/p.distance_unit) 
       AND p.latpoint + (p.radius/p.distance_unit) 
      AND z.longitude 
      BETWEEN p.longpoint - (p.radius/(p.distance_unit * COS(RADIANS(p.latpoint)))) 
       AND p.longpoint + (p.radius/(p.distance_unit * COS(RADIANS(p.latpoint)))) 
     ) AS d 
    WHERE distance <= radius 
    ORDER BY distance ASC'; 

В дополнении к этому мне нужно добавить некоторые count(*) -statements вернуть количество пассажиров в каждом городе. Так что я пытался добавить их так:

SELECT population, AccentCity, Country, code3l, name, City, Region, 
     Latitude, Longitude, distance,id, 
     (select count(*) from passengers where city_id = d.id) AS passenger, 
     (select count(*) from passengers where city_id = d.id AND 
           start = "'.$icao.'") AS passengerFromHere, 
     (select count(*) from passengers where city_id = d.id AND 
          destination = "'.$icao.'") AS passengerToHere 
FROM (
     SELECT z.population,z.id, 
... 

но таблица с именем passengers быстро растет, и что общее время выполняющийся для заявления

Я есть способ присоединиться тяжелый passengers стол, имея тот же результат (массив городов с их соответствующими пассажирами) в лучшем времени выполнения

+0

попробуйте использовать 'count (id)' вместо 'count (*)', поскольку он выберет все в таблице. вы всегда должны избегать использования *. –

+0

Производительность ухудшается с помощью тома - явный признак того, что вам нужно хорошее оборудование, которое может поддержать рост ваших данных. Есть только так много, что вы можете сделать, пока не нажмете ограничение на одно из ваших устройств. Теперь вы можете попытаться взломать и слэш, а что нет, но в конце - даже лучший код или запрос когда-либо попадают на этот аппаратный лимит. –

+0

нашел эту интересную статью: [link] (http://www.howtogeek.com/howto/programming/speed-up-your-web-site-with-mysql-query-caching/). попробуйте сыграть с этими значениями в файле конфигурации: 'query_cache_size = 268435456' ' query_cache_type = 1' 'query_cache_limit = 1048576' –

ответ

0

Я достал счетчик-счетчик из SQL. Встроенные функции PHP, что петли через каждый город и добавляет количество пассажирских в город, если ключ с именем CITY_ID существует

if(isset($cityArray[$passengers[$key[$i]]->city_id]))

В качестве замены для SQL заявления:

(select count(*) from passengers where city_id = d.id AND 
          start = "'.$icao.'") AS passengerFromHere, 

функция CodeIgniter, что я придумал, это:

public function add_PassengersFromHereToCitys($icao, $cityArray){ 

      $query = $this->db->select('count(city_id) as passengers, city_id')->from('passengers')->where('start', $icao)->group_by('city_id')->get(); 
      $passengers = $query->result(); 

      $key = array_keys($passengers); 
      $size = sizeOf($key); 
      for ($i=0; $i<$size; $i++){ 

       if(isset($cityArray[$passengers[$key[$i]]->city_id])){ 
        $cityArray[$passengers[$key[$i]]->city_id]->passengerFromHere = $passengers[$key[$i]]->passengers; 
       } 

      } 

      return $cityArray; 
     } 

сделали это с 2 count(*) соответственно.

Теперь с этой петлей php получение желаемых результатов выполняется быстрее, чем вытягивание даты в sql-statement. Однако, если у кого-то есть идея изменить инструкцию sql. Дай мне знать!