Что лучше один запрос или три ?

accido

Новичок
Кратко о проблеме: в Wordpress класс WP_Query для выборки постов из БД - это тихий ужас, который без бубна нормально не по-используешь, кроме того вообще весь API по работе с БД у них основан на драйвере mysql. Вообщем, есть один запрос для выборки постов, атачей и терм-таксономий. Что лучше один запрос, или выбирать посты, атачи и термы отдельно( без GROUP BY)? И второй вопрос - можно ли улучшить большой запрос?
Сам запрос:
PHP:
SELECT 
  GROUP_CONCAT( CAST( tr2.term_taxonomy_id AS CHAR ) SEPARATOR ',' ) ttid,
  GROUP_CONCAT( CAST( tt2.taxonomy AS CHAR ) SEPARATOR ',' ) taxonomy,
  GROUP_CONCAT( CAST( t2.term_id AS CHAR ) SEPARATOR ',' ) tid,
  GROUP_CONCAT( CAST( t2.name AS CHAR ) SEPARATOR ',' ) tname,
  GROUP_CONCAT( CAST( t2.slug AS CHAR ) SEPARATOR ',' ) tslug,
  y.*
FROM (
  SELECT 
    GROUP_CONCAT( CAST( p3.ID AS CHAR ) SEPARATOR ',' ) attaches,
    m1.meta_value thumb_id,
    p1.*
  FROM (
    SELECT p2.* FROM wp_posts p2 USE INDEX(  PRIMARY, type_status_date )
    WHERE p2.post_type='cars' AND p2.post_status='publish' AND p2.ID NOT IN (
      SELECT tr1.object_id FROM wp_term_relationships tr1 USE INDEX( PRIMARY )
      INNER JOIN wp_term_taxonomy tt1 USE INDEX( PRIMARY ) ON tt1.term_taxonomy_id = tr1.term_taxonomy_id
      WHERE tt1.term_id IN ('179,278')
    )
    ORDER BY p2.post_date ASC
    LIMIT 30 OFFSET 0  ) p1
  LEFT OUTER JOIN wp_postmeta m1 USE INDEX( post_id, meta_key ) ON m1.post_id = p1.ID AND m1.meta_key='_thumbnail_id'
  LEFT OUTER JOIN wp_posts p3 USE INDEX( type_status_date, post_parent ) 
    ON p3.post_type = 'attachment' AND p3.post_status='inherit' AND p3.post_parent = p1.ID
  GROUP BY p1.ID ORDER BY NULL
) y
LEFT OUTER JOIN wp_term_relationships tr2 USE INDEX( PRIMARY ) ON tr2.object_id = y.ID
LEFT OUTER JOIN wp_term_taxonomy tt2 USE INDEX( PRIMARY ) ON tt2.term_taxonomy_id = tr2.term_taxonomy_id
LEFT OUTER JOIN wp_terms t2 USE INDEX( PRIMARY ) ON t2.term_id = tt2.term_id 
GROUP BY y.ID ORDER BY NULL
план запроса( mysql v.5.5.27 ):
 

accido

Новичок
Немного модернизировал запрос, пример:
PHP:
SELECT
  UNIX_TIMESTAMP( y.post_date ) ts_id,
  GROUP_CONCAT( CAST( tr2.term_taxonomy_id AS CHAR ) SEPARATOR ',' ) ttid,
  GROUP_CONCAT( CAST( tt2.taxonomy AS CHAR ) SEPARATOR ',' ) taxonomy,
  GROUP_CONCAT( CAST( t2.term_id AS CHAR ) SEPARATOR ',' ) tid,
  GROUP_CONCAT( CAST( t2.name AS CHAR ) SEPARATOR ',' ) tname,
  GROUP_CONCAT( CAST( t2.slug AS CHAR ) SEPARATOR ',' ) tslug,
  y.*
FROM (
  SELECT 
    GROUP_CONCAT( CAST( p3.ID AS CHAR ) SEPARATOR ',' ) attaches,
    m1.meta_value thumb_id,
    p1.*
  FROM (
    SELECT p2.* FROM wp_posts p2 USE INDEX(  PRIMARY, type_status_date )
    WHERE p2.post_type='cars' AND p2.post_status='publish' AND p2.ID NOT IN (
      SELECT tr1.object_id FROM wp_term_relationships tr1 USE INDEX( PRIMARY )
      INNER JOIN wp_term_taxonomy tt1 USE INDEX( PRIMARY ) ON tt1.term_taxonomy_id = tr1.term_taxonomy_id
      WHERE tt1.term_id IN (179,278)
    )
    ORDER BY p2.post_date DESC
    LIMIT 30 OFFSET 0  ) p1
  LEFT OUTER JOIN wp_postmeta m1 USE INDEX( post_id, meta_key ) ON m1.post_id = p1.ID AND m1.meta_key='_thumbnail_id'
  LEFT OUTER JOIN wp_posts p3 USE INDEX( type_status_date, post_parent ) 
    ON p3.post_type = 'attachment' AND p3.post_status='inherit' AND p3.post_parent = p1.ID
  GROUP BY p1.ID ORDER BY NULL
) y
LEFT OUTER JOIN wp_term_relationships tr2 USE INDEX( PRIMARY ) ON tr2.object_id = y.ID
LEFT OUTER JOIN wp_term_taxonomy tt2 USE INDEX( PRIMARY ) ON tt2.term_taxonomy_id = tr2.term_taxonomy_id
LEFT OUTER JOIN wp_terms t2 USE INDEX( PRIMARY ) ON t2.term_id = tt2.term_id 
GROUP BY y.ID ORDER BY NULL
план у него остался тот же, и решил сравнить скорость с тремя запросами, вот их примеры
PHP:
SELECT p.* FROM wp_posts p USE INDEX(  PRIMARY, type_status_date )
WHERE p.post_type='cars' AND p.post_status='publish' AND p.ID NOT IN (
  SELECT tr.object_id FROM wp_term_relationships tr USE INDEX( PRIMARY )
  INNER JOIN wp_term_taxonomy tt USE INDEX( PRIMARY ) ON tt.term_taxonomy_id = tr.term_taxonomy_id
  WHERE tt.term_id IN (179,278)
)
ORDER BY p.post_date DESC
LIMIT 30 OFFSET 0

PHP:
SELECT 
  p.post_parent,
  p.ID,
  m.meta_value thumb_id
FROM wp_posts p USE INDEX ( post_parent, type_status_date )
LEFT OUTER JOIN wp_postmeta m USE INDEX( post_id, meta_key ) 
  ON m.post_id = p.post_parent AND m.meta_key='_thumbnail_id'
WHERE p.post_type='attachment' 
  AND p.post_status='inherit'
  AND p.post_parent IN (1331,1528,1559,1522,1534,1552,1516,1542,1532,1538,1555,1540,1545,1557,1518,1549,1524,1563,1543,1547,1548,1514,1554,1544,1553,1546,1561,1550,1526,1551)

PHP:
SELECT 
  tr.object_id ID,
  GROUP_CONCAT( CAST( tr.term_taxonomy_id AS CHAR ) SEPARATOR ',' ) ttid,
  GROUP_CONCAT( CAST( tt.taxonomy AS CHAR ) SEPARATOR ',' ) taxonomy,
  GROUP_CONCAT( CAST( t.term_id AS CHAR ) SEPARATOR ',' ) tid,
  GROUP_CONCAT( CAST( t.name AS CHAR ) SEPARATOR ',' ) tname,
  GROUP_CONCAT( CAST( t.slug AS CHAR ) SEPARATOR ',' ) tslug
FROM wp_term_relationships tr USE INDEX( PRIMARY )
STRAIGHT_JOIN wp_term_taxonomy tt USE INDEX( PRIMARY ) ON tt.term_taxonomy_id=tr.term_taxonomy_id
STRAIGHT_JOIN wp_terms t USE INDEX( PRIMARY ) ON t.term_id=tt.term_id
WHERE tr.object_id IN (1331,1528,1559,1522,1534,1552,1516,1542,1532,1538,1555,1540,1545,1557,1518,1549,1524,1563,1543,1547,1548,1514,1554,1544,1553,1546,1561,1550,1526,1551)
GROUP BY ID ORDER BY NULL

цикл из 1000 построений одной и той же структуры дал такие результаты:
первый вариант:
PHP:
Start time : '1.344', memory 19.37
Finish time : '150.313', memory 20.07
и, соответственно, второй:
PHP:
Start time : '1.281', memory 19.37
Finish time : '120.031', memory 20.12
П.С. Использовалось тормозное окружение easyphp 18.1. Че с ним не так - не знаю, но на денвере, к примеру, все летает. Тут же вывод простого пхпинфо 500мс. Да и мускул на нем тоже тормозит, поэтому если не забуду проведу второй тест на боевом серваке.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
а по каким критериям надо оценивать варианты?
 

accido

Новичок
а по каким критериям надо оценивать варианты?
Надо из мускула обычными sql-запросами получить данные и связать эти данные в одну структуру(массив указателей на обьекты), отсортированной в нужном порядке. Ясно, что ели сервер БД и веб-сервер физически в разных местах, то и запросы к БД будут идти дольше, поэтому лучше получить данные одним запросом. Вот и хочется узнать не на много ли это затратней, чем несколькими запросами, если вообще затратней. Это чисто теоретически, потому что все равно запрос будет закеширован надолго и с концами. :)
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Надо из мускула обычными sql-запросами получить данные и связать эти данные в одну структуру(массив указателей на обьекты), отсортированной в нужном порядке. Ясно, что ели сервер БД и веб-сервер физически в разных местах, то и запросы к БД будут идти дольше, поэтому лучше получить данные одним запросом. Вот и хочется узнать не на много ли это затратней, чем несколькими запросами, если вообще затратней. Это чисто теоретически, потому что все равно запрос будет закеширован надолго и с концами. :)
1. затраты на передачу данных в пределах сегмента локальной сети незначительны на фоне затрат на исполнение запроса, а кеш к запросу отношения не имеет
2. конечная цель очевидна, я ставлю вопрос о том, по каким критериям следует оценивать варианты
уточню: можно оценивать по нагрузке на процессор, на диск, на потребление памяти, по времени исполнения, по количеству исполнений в секунду при N одновременных запросов, и в каждом случае ответ может быть разный

>Это чисто теоретически
если твой вопрос на самом звучит так: "лучше один абстрактный запрос в вакууме, или три?" - мой вопрос, да и сама тема, не имеют смысла, конечно
 
Сверху