Оптимизировать этот запрос для 1000 пациентов в таблице пациентов

Здесь очень простой метод

let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
2
задан Jean 19 February 2019 в 13:50
поделиться

3 ответа

Низкая производительность в любой системе RDBM обусловлена ​​плохим дизайном. В своей скрипте SQL вы сохраняете числа в поле varchar. Ваш текущий движок таблиц - MyISAM, который не поддерживает отношения !? No relationships => no index => no quick lookups

Чтобы улучшить производительность, я предлагаю вам изменить дизайн стола. Таблица счетов может иметь следующие изменения. Change Engine to InnoDB и

ALTER TABLE `invoice` ENGINE = Innodb;

ALTER TABLE `invoice` 
CHANGE COLUMN `patientid` `patientid` INT(12) UNSIGNED NOT NULL ,
CHANGE COLUMN `ammount` `ammount` DECIMAL(14,2) NOT NULL ,
CHANGE COLUMN `discount` `discount` DECIMAL(3,2) NULL DEFAULT '0' ,
ADD INDEX `fk_invoice_patient_idx` (`patientid` ASC);
ALTER TABLE `invoice` 
ADD CONSTRAINT `fk_invoice_patient`
  FOREIGN KEY (`patientid`)
  REFERENCES `test`.`patient` (`patientid`)
  ON DELETE RESTRICT
  ON UPDATE CASCADE;

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

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

0
ответ дан krish KM 19 February 2019 в 13:50
поделиться
SELECT patientid, firstname,lastname,mobilephone,email, FORMAT( COALESCE(
    ( SELECT SUM(ammount)-SUM((ammount * (discount/100))) 
    FROM invoice 
    INNER JOIN patient
    ON invoice.patientid = patient.patientid 
    and invoicednumber >0) - 
    ( SELECT SUM(ammount) 
      FROM payment 
      INNER JOIN patient 
      ON payment.patientid = patient.patientid ),0),0) AS answer, 
    DATE_FORMAT(( SELECT max(paymentdate) 
                  FROM payment 
                  INNER JOIN patient 
                  ON payment.patientid = patient.patientid ),'%d-%m-%Y') As lastpaymentdate 
from patient WHERE 1 

Это будет работать быстрее !!!!

Попробуйте и дайте мне знать

ОБНОВЛЕНИЕ
Я заменил предложение WHERE на внутреннее соединение, которое поможет быстро получить данные .
Я также добавил бы, что если индексы отсутствуют по первичному ключу, тогда добавьте.

0
ответ дан 19 February 2019 в 13:50
поделиться

Хотя пример, ваше предложение WHERE в основном возвращает ВСЕХ пациентов. Вероятно, что убивает вашу производительность, так это то, что вы делаете 3 коррелированных запроса в своих списках полей, каждый раз запрашивая у каждого человека. Один раз для выставления счета и два раза для платежей.

Вместо этого я реструктурировал запрос на основе Pre-Query LEFT-JOIN в таблицы счетов и платежей. Если вы посмотрите, таблица счетов-фактур предварительно суммируется с GROUP BY каждого идентификатора пациента. Аналогично по таблице платежей GROUP BY каждого пациента. Таким образом, в худшем случае каждый подзапрос будет возвращать по САМОЙ одной записи для данного пациента с суммой всех счетов и соответствующих скидок. Для платежей - сумма всех платежей И самая последняя дата.

Таким образом, начиная с таблицы пациентов, я могу присоединиться к общему идентификатору пациента, в котором вы можете увидеть упрощенные итоговые значения для конечного результата, и они будут применимы для всех пациентов. Да, вы можете добавить критерии WHERE для дальнейшего ограничения, но это должно работать значительно лучше.

SELECT 
        p.patientid, 
        p.firstname, 
        p.lastname, 
        p.mobilephone, 
        p.email,
        coalesce( PatInv.JustSumOfAmount - PatInv.DiscountedAmounts, 0 )
            - coalesce( PatPay.PaidAmounts, 0 ) Answer,
        case when PatPay.PatientID IS NULL
            then ' '
            else Date_format( PatPay.LastPaymentDate, '%d-%m-%Y') end lastpaymentdate
    FROM 
        patient p
            LEFT JOIN
            ( select 
                    i.patientID,
                    sum( i.ammount ) justSumOfAmount,
                    sum( i.ammount * ( discount / 100 )) as discountedAmounts
                from
                    invoice i
                where
                    i.invoicedNumber > 0
                group by
                    i.patientID
                order by
                    i.patientid ) PatInv
                on p.patientid = patInv.patientID
            LEFT JOIN
            ( SELECT
                    pay.patientID, 
                    Sum(pay.ammount) paidAmounts,
                    max( pay.paymentDate ) LastPaymentDate
                FROM
                    payment pay
                group by
                    pay.patientID 
                order by
                    pay.patientid ) PatPay
                on p.patientID = patPay.PatientID

Я разместил этот запрос на SQL Fiddle Кроме того, просматривая ваши таблицы, таблицы счетов-фактур и счетов-фактур ДОЛЖНЫ КАЖДЫЙ иметь индекс идентификатора пациента, чтобы помочь оптимизировать запросы. Я не знаю, был ли это пример недосмотра с вашего sql-fiddle vs production, но это тоже повлияло бы на производительность.

У меня есть опция SQLFiddle, которая занимает 5 мс против ваших 2-3 мс, но это только для нескольких предоставленных записей. Я бы поспорил, что против ваших 1000+ пациентов и 1000 транзакций в каждом счете и таблице платежей это сделает этот вариант запроса быстрее, чем коррелированные запросы.

Думайте о своем запросе как об этом. У меня 1000 пациентов. Запросите таблицу счетов 1000 раз, запросите таблицу платежей 2000 раз (1000 для суммы платежей, еще 1000 раз для самой последней даты на пациента).

Мой запрос - предварительно запросите таблицу счетов и суммируйте 1 запись на пациента. Предварительно запросите таблицу платежей и суммируйте 1 запись на пациента. Присоедините пациентов к этим двум подтаблицам напрямую по ID.

0
ответ дан DRapp 19 February 2019 в 13:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: