2009-09-01 2 views
0

У меня есть таблица,Как улучшить этот запрос?

| 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 

дается экспертом, который не является технически правильным (что-то делать с вами не SELECT * .. GROUP), но дает результаты, намного быстрее, с случай, когда

SELECT * FROM PAGELETS WHERE 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 запроса дого правильный, чтобы достичь скорости некорректного одного 2) или есть способ исправить неправильные один к (я не забочусь о строгости)

+0

Все, SELECT DISTINCT * 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; Решает, но как мне сделать это быстрее сейчас? – 2009-09-01 11:10:13

+0

mysql> EXPLAIN SELECT DISTINCT * FROM PAGELETS WHERE pagelet_shingle IN (SELECT pagelet_shingle FROM PAGELETS GROUP BY page__Single_HINGING COUNT (DISTINCT page_key)> 1) ORDER BY pagelet_shingle; | 1 | ПЕРВИЧНЫЙ | PAGELETS | ВСЕ | NULL | NULL | NULL | NULL | 6959 | Использование где; Использование временных; Использование filesort | | 2 | ЗАВИСИМОЕ СУБКЕРУ | PAGELETS | индекс | NULL | pagelet_shingle | 8 | NULL | 6959 | Использование индекса | – 2009-09-01 11:11:55

+0

Я добавил индекс, | PAGELETS | CREATE TABLE 'PAGELETS' ( ' page_key' INT (32) NOT NULL без знака, 'pagelet_serial' INT (32) NOT NULL без знака, ' pagelet_shingle' INT (32) NOT NULL без знака, KEY 'pagelet_shingle' (' pagelet_shingle ') ) ENGINE = MyISAM DEFAULT CHARSET = utf8 | SELECT DISTINCT * FROM PAGELETS WHERE pagelet_shingle IN (SELECT pagelet_shingle FROM PAGELETS GROUP BY page__Single_HINGING COUNT (DISTINCT page_key)> 1) ORDER BY pagelet_shingle; все еще медленно, как ад. – 2009-09-01 11:19:52

ответ

0

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

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

+0

На самом деле, почему бы вам порекомендовать второй, если он медленный? Я не хочу использовать второй, потому что это будет применяться к набору данных более чем в 20 раз по сравнению с его текущим размером. SELECT DISTINCT * FROM PAGELETS WHERE pagelet_shingle IN (SELECT pagelet_shingle FROM PAGELETS GROUP BY page__HINGING COUNT (DISTINCT page_key)> 1) ORDER BY pagelet_shingle; Решает его, но любой способ ускорить его с помощью индекса? (Я не знаю, что я должен индексировать по этому вопросу, я попробовал ключ индексирования (page_shingle, page_key), но он был одинаково медленным – 2009-09-01 11:03:33

+0

Упс, было немного рано для меня. Конечно, я имел в виду первый. –

0

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

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

Nope - не в MySQL (Ref: ENGINE = MyISAM) – goddva

+0

(1,64,8) (1,64,9) (1,64,10) (1,64,11) (1,64) , 12) (1,64,13) (1,64,14) (1,64,15) (1,64,16) (1,41,20) (1,41,21) (1,41,22) (1,99,48) (1,99,49) (1,99,50) (1,99,51) (1,99,52) (1,99,53) (1,99,54) (1,99,58) (1,99,59) (1,99,60) (1,99,61) На самом деле, действительно, я не вижу ничего, что имеет разные значения page_key; тот, где проблема page_key = 57 все еще существует (она не найдена внутри результирующего набора, потому что она встречается более одного раза) – 2009-09-01 11:09:17

0

Что

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

дает вам?

+0

| page_key | pagelet_serial | pagelet_shingle | + ---------- + ---------------- + ----------------- + | 1 | 56 | 1 | | 1 | 56 | 2 | | 1 | 56 | 3 | | 2 | 186 | 8 | | 1 | 64 | 8 | | 1 | 64 | 9 | | 2 | 186 | 9 | | 1 | 64 | 10 | | 2 | 186 | 10 | – 2009-09-01 10:55:02

+0

Не то, что я действительно хочу: (1,56,1) (1,56,2) (1,56,3) (2,186,8) (1,64,8) (1,64 , 9) (2,186,9) (1,64,10) (2,186,10) (1,64,11) (2,186,11) (1,64,12) (2,186,12) (1,64,13) (2,186,13) (1,64,14) (2,186,14) (1,64,15) (2,186,15) (1,64,16) (2,186,16) (1,41,20) (2,203,20) (1,41,21) (2,203,21) (2,203,22) (1,41,22) (1,21,27) (1,21,28) (1,21,29) (1,21,30) (1,21,31) (1,21,32) (1,21,33) (1,21,34) (1,21,35) (1,21,36) (1,21,37) (1,21,38) (1,21,39) (1,21,40) (1, 21,41) (1,21,42) (1,21,43) (1,21,44) (2,228,48) (1,99,48) (2,228,49) (1,99,49) (2,228,50) (1,99,50) (2,228,51) (1,99,51) (2,228,52) (1,99,52) – 2009-09-01 10:58:58

0

использование GROUP BY и HAVING, например.

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

дополнительно вы можете сделать самостоятельно присоединиться к выходу все столбцы, хотя в MySQL, он должен работать таким образом (отличающуюся от стандарта SQL)

0

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

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)

Смежные вопросы