2013-08-01 4 views
2

Хорошо, наиболее вероятно, что я делаю что-то неправильно, но следуя советам пользователя здесь я запускаю этот запрос:граф запроса занимает слишком много времени - прошло более 24 часов

SELECT id, item, 
    (SELECT COUNT(item) FROM Table1 WHERE id=a.id AND item=a.item) cnt 
FROM (SELECT DISTINCT a.id,b.item FROM Table1 a, Table1 b) a 
ORDER BY id, item; 

на этой таблице:

ID   ITEM 
----------------- 
0001  345 
0001  345 
0001  120 
0002  567 
0002  034 
0002  567 
0003  567 
0004  533 
0004  008 
... 

для того, чтобы получить этот результат:

ID ITEM CNT 
1 8  0 
1 34  0 
1 120  1 
1 345  2 
1 533  0 
1 567  0 
2 8  0 
2 34  1 
... 

но это занимает слишком много времени, и запрос по-прежнему работает Afte r в день ... Есть ли способ улучшить производительность? У меня есть около 4 миллион строк

Спасибо

+0

Вы добавили указатели и ключи? – Avitus

+3

Запрос, который вы используете в предложении FROM, забивает базу данных! Вы присоединяетесь к таблицам без каких-либо условий, поэтому он по существу делает кросс-соединение каждой записи, и когда есть 4 миллиона записей, которые будут ОЧЕНЬ долго! – PaReeOhNos

+0

Прошу прощения, я новичок в mysql, поэтому я не уверен, что это такое - так что ответ - нет. Не объясните, что вы имеете в виду? – user2578185

ответ

6

Вашего запроса является довольно запутанным. Я думаю, вы просто хотите посчитать комбинации id и item. Если да, то это простое агрегирование:

select id, item, count(*) 
from Table1 a 
group by id, item; 

Если вы хотите, чтобы все идентификаторы и элементы для отображения, а затем использовать драйвер таблицы:

select driver.id, driver.item, coalesce(count(t1.id), 0) 
from (select id.id, item.item 
     from (select distinct id from Table1) id cross join 
      (select distinct item from Table1) item 
    ) driver left outer join 
    Table1 t1 
    on driver.id = t1.id and driver.item = t1.item 
group by driver.id, driver.item; 

Исходный запрос имеет это заявление:

(SELECT DISTINCT a.id,b.item FROM Table1 a, Table1 b) a 

Это делает полный декартовой продукт, а затем делает отдельный. Итак, если ваша таблица имеет 100 000 строк, то промежуточная таблица содержит 10 000 000 000 строк для отдельных (я не думаю, что MySQL оптимизирует это немного лучше). Выполнение отдельных первых (как для драйвера) значительно снижает объем данных.

EDIT:

Есть класс вопросов SQL, где вы должны смотреть на все комбинации из двух или более элементов, а затем определить значения для всех (даже те, которые не существуют в данных) или найти те, которые являются не в данных. Эти проблемы создают одну и ту же проблему: как вы получаете информацию о значениях не в данных?

Решение, которое я защищаю, состоит в том, чтобы создать таблицу со всеми возможными комбинациями, а затем использовать left [outer] join для остальных таблиц. Я называю это таблицей «драйвер», потому что строки в этом запросе «приводят» запрос, определяя популяцию для последующих объединений.

Эта терминология вполне соответствует ссылке в комментарии. В комментарии используется термин с точки зрения оптимизатора. Некоторые алгоритмы объединения - особенно вложенный цикл и индексный поиск - обрабатывают обе стороны соединения по-разному; для них одна сторона - таблица «водитель/водитель». Например, при объединении из большой таблицы в небольшую справочную таблицу большая таблица является таблицей вождения, а другая таблица доступна через индекс. Другие алгоритмы объединения - например, объединение слияния и хеш-соединения (в общем) - рассматривают обе стороны одинаково, поэтому концепция здесь менее применима.

С логической точки зрения я использую его для обозначения запроса, который определяет население. Важное сходство состоит в том, что для левого/правого внешнего соединения оба определения на практике одинаковы. Оптимизатор обычно выбирает первую таблицу в left join в качестве «драйвера», поскольку он определяет выходные строки.

+0

«Что такое дорожный стол» http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:192812348072 Вы используете его в несколько другом контексте. +1 для дополнительного объяснения. –

+0

@JanDoggen. , , Я попытался объяснить, что я имею в виду в отредактированном комментарии. –

1

Если единственное, что вы хотите достичь, это граф, сгруппированные по id и item, почему вы не просто:

SELECT ID, Item, COUNT(1) 
FROM Table 1 
GROUP BY ID, Item 

Это так просто!

+1

Меня также интересуют случаи, когда число равно 0, но – user2578185

+0

Это не то, что он хочет, посмотрите на 0 в столбце CNT: пункты 8 и 34 появляются хотя бы для одного ID, кроме 1, для ID = 1 их count = 0 –

-2

Проблема скорости из вашего запроса, скорее всего, «отличная», которая функционально выбирает все данные, сортирует, а затем удаляет дубликаты перед возвратом результатов. «Отличная» - дорогая функция.

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