Как улучшить этот запрос? - PullRequest
0 голосов
/ 01 сентября 2009

У меня есть стол,

| PAGELETS | CREATE TABLE `PAGELETS` (
  `page_key` int(32) unsigned NOT NULL,
  `pagelet_serial` int(32) unsigned NOT NULL,
  `pagelet_shingle` int(32) unsigned NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 

Я бы хотел:

1) Find all the pagelet_shingles where quantity > 1 ( occurs more than once)
2) out of these only output those that have different page_key

Это запрос, который дает полу-правильный ответ:

SELECT * FROM PAGELETS WHERE pagelet_shingle IN( SELECT pagelet_shingle FROM PAGELETS GROUP BY pagelet_shingle HAVING COUNT(DISTINCT page_key) > 1) ORDER BY pagelet_shingle;

К сожалению, для небольшого набора данных это занимает около 18 секунд;

У меня есть другой запрос,

SELECT dt1.* FROM 
(SELECT * FROM PAGELETS 
GROUP BY page_key, pagelet_shingle HAVING COUNT(*) = 1) 
dt1 JOIN 
(SELECT * FROM PAGELETS GROUP BY pagelet_shingle HAVING COUNT(*) > 1) 
dt2 USING (pagelet_shingle) ORDER BY pagelet_shingle

дано экспертом, который технически не корректен (что-то с вами не может ВЫБРАТЬ * .. ГРУППА), но дает результаты НАМНОГО быстрее, в случае

ВЫБРАТЬ * ИЗ ПАГЕТЕРОВ, ГДЕ pagelet_shingle = 57

+----------+----------------+-----------------+
| page_key | pagelet_serial | pagelet_shingle |
+----------+----------------+-----------------+
|        1 |             99 |              57 | 
|        1 |             99 |              57 | 
|        2 |            228 |              57 | 
|        2 |            228 |              57 | 
+----------+----------------+-----------------+

Полукорректный запрос дает

+----------+----------------+-----------------+
| page_key | pagelet_serial | pagelet_shingle |
+----------+----------------+-----------------+
|        1 |             99 |              57 | 
|        1 |             99 |              57 | 
|        2 |            228 |              57 | 
|        2 |            228 |              57 | 
+----------+----------------+-----------------+ 

Хотя в неправильном запросе нет набора pagelet_shingle = 57

Мой желаемый результат -

+----------+----------------+-----------------+
| page_key | pagelet_serial | pagelet_shingle |
+----------+----------------+-----------------+
|        1 |             99 |              57 |  
|        2 |            228 |              57 | 
+----------+----------------+-----------------+ 

Каждый случай только один раз.

a pagelet_shingle, встречающийся дважды в одном и том же pagelet_serial, будет опущен.

Так что я хотел бы спросить следующее: 1) Есть ли способ ускорить csemi orrect запрос, чтобы достичь скорости неправильного 2) или есть способ исправить неправильный, чтобы получить результат правильного (меня не волнует строгость)

Ответы [ 6 ]

0 голосов
/ 01 сентября 2009

Вы пытались использовать exists вместо in?

Проверьте это: http://decipherinfosys.wordpress.com/2007/01/30/in-vs-exists/

Надеюсь, это поможет

0 голосов
/ 01 сентября 2009

Судя по тому, что я прочитал, вы ищете:

SELECT DISTINCT p1.page_key, p1.pagelet_serial, p1.pagelet_shingle
  FROM PAGELETS p1
  JOIN PAGELETS p2 ON p2.page_key         = p1.page_key
                  AND p2.pagelet_serial   = p1.pagelet_serial
                  AND p2.pagelet_shingle <> p1.pagelet_shingle

Этот запрос будет полностью использовать индекс для (page_key, pagelet_serial) и должен завершиться за десятые секунды, а не секунды.

Если это не то, что вы искали, пожалуйста, покажите нам, какой результат вы ожидаете, если бы значения в вашей таблице были такими: (1,2,3), (1,2,3), (1,1 , 3), (1,1,3), (1,2,4), (1,2,4), (1,1,4), (1,1,4)

0 голосов
/ 01 сентября 2009

используйте GROUP BY и HAVING, например,

  SELECT *
    FROM `pagelets`
GROUP BY `pagelet_shingle`
  HAVING COUNT(*) > 1

Кроме того, вы можете выполнить самообъединение для вывода всех столбцов, хотя в mysql это должно работать так (отличается от стандарта SQL)

0 голосов
/ 01 сентября 2009

Что такое

SELECT * FROM PAGELETS GROUP BY pagelet_serial, pagelet_shingle HAVING COUNT(*) > 0

дает тебе?

0 голосов
/ 01 сентября 2009

этот вопрос не решает вашу проблему?

SELECT dt1.* FROM 
(SELECT DISTINCT * FROM PAGELETS 
GROUP BY page_key, pagelet_shingle HAVING COUNT(*) = 1) 
dt1 JOIN 
(SELECT * FROM PAGELETS GROUP BY pagelet_shingle HAVING COUNT(*) > 1) 
dt2 USING (pagelet_shingle) GROUP BY pagelet_shingle
0 голосов
/ 01 сентября 2009

Похоже, SELECT DISTINCT p.* ... будет вашим выбором.

P.S. И я очень рекомендую второй! сделайте все медленно (как вы только что заметили) и должны использоваться только при необходимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...