2014-10-21 3 views
0

У меня есть следующий запрос в MySQLMySQL присоединился подзапросов оптимизации

select * from 
    (
     select asiento, fecha, sum(debe) as debe, sum(haber) as haber 
     from apuntes 
     where apuntes.sobreescrito is null 
     group by asiento, fecha 
     order by fecha, asiento 
    )asientos 
    left join 
    (
     select id_diario, asiento, fecha, sum(debe) as debe, sum(haber) as haber 
     from apuntes 
     where apuntes.sobreescrito is not null 
     group by asiento, fecha, id_diario 
     order by fecha, asiento 
    )asientos_antiguos 
    on asientos.asiento = asientos_antiguos.asiento and asientos.fecha = asientos_antiguos.fecha 
    where 
     asientos_antiguos.debe <> asientos.debe 
     or 
     asientos_antiguos.haber <> asientos.haber 

Тхи первого подзапроса (asientos) возвращает около 20к записей, в то время как второй запрос, в нормальной ситуации, не должна возвращать не более thatn 20k записей, который дает приемлемый запрос в 3-4 секунды, но теоретически он может дублировать записи для каждой операции, поэтому я тестирую с производимыми 100k записями, и это занимает около 30 секунд (неприемлемо).

В этот момент я попытался создать индексы для полей «asiento» и «fecha», но подзапросы не выиграют от этого. Кроме того, я создал два представления для каждого подзапроса, надеясь, что я смогу создать индекс в этих подзонах, но ограничения на просмотр включают «без индексов».

Любая помощь будет оценена по достоинству.

EDIT 1

Хорошо, я постараюсь дать объяснение того, что я пытаюсь достичь, и не стесняйтесь, чтобы исправить свой английский, I'm буду использовать финансовые слова, которые я, вероятно, don' Знаю.

Я разработал веб-приложение, которое читает файлы excel с книжными записями (каждый из которых содержит обычно 20 тыс. Записей) и сохраняет эти записи в таблице (в моем случае, как и в самом деле).

Иногда некоторые из этих записей могут быть перезаписаны в случае, если поля «fecha» и «asiento» одинаковы, а поле «id_diario» отличается (ПРИМЕЧАНИЕ: каждая книга excel генерирует набор записей книг с его собственный «id_diario», поэтому я могу отличить старые записи)

На данный момент все идет хорошо, но теперь мне нужно сгенерировать отчет, показывающий, что в какой-то момент перезаписаны записи в книге (финансовое слово, не указано знаете, правильно ли это) имеют другую сумму, чем новые, которые их перезаписали.

И вот когда я пришел с этим запросом, где первый подзапрос принимает все записи, которые не перезаписываются (apuntes.sobreescrito - NULL), а второй подзапрос принимает все перезаписанные записи, соответствующие 1-му подзапросу.

В моем тестовом примере второй подзапрос генерирует 3 перезаписываемых записи для каждой допустимой записи в книге (было 3 операции перезаписи), что означает сравнение 60k и 20k записей.

В качестве следующего шага я буду использовать операцию «GROUP_CONCAT», чтобы сгенерировать json-formated массив с результатами второго запроса, но в 1-м я должен исправить проблему с производительностью.

+0

Подзапросы могут использовать индексы внутри, но при объединении результатов этих подпрозов индексы не используются. Возможно, это будет возможно без подзапросов, но мне нужно будет больше узнать о ваших данных (например, что такое столбец id_diaro, который возвращается только из второго запроса sub?) – Kickstart

+1

Не можете описать, что делает запрос? Возможно, существует более простой способ реализации логики. –

+0

Просто прочитайте свое редактирование. На выходе вы хотите, чтобы перечисленные записи не были обновлены (т. Е. Не совпадают записи во втором подзапросе) или только те, где было обновление, и суммы разные? – Kickstart

ответ

1

Удивительно, если вы можете использовать более простой запрос для определения записей, где есть несоответствие, а затем просто получить реальные данные для них. Это может помочь, если количество измененных записей, которые вас интересуют, - это всего лишь небольшое количество всех записей.

Например, что-то вроде этого нужно найти записи, которые были изменены -

SELECT asiento, fecha 
FROM 
( 
    SELECT id_diario, asiento, fecha, SUM(debe) AS debe, SUM(haber) AS haber 
    FROM apuntes 
    GROUP BY id_diario, asiento, fecha 
) sub0 
GROUP BY asiento, fecha 
HAVING MIN(debe) != MAX(debe) 
OR MIN(haber) != MAX(haber) 

Вы могли бы, возможно, использовать эту функцию, чтобы сузить фактические записи, которые нужно проверить.

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