2015-06-15 5 views
1

Этот запрос принимает динамический ввод вместо cg.ownerid IN (294777,228649, 188464). Когда вход увеличивается в состоянии IN, запрос занимает слишком много времени для выполнения. Пожалуйста, предложите мне способ его оптимизации.Как оптимизировать sql-запрос

Например, запрос ниже занимает 4 секунды, если я уменьшаю список до только IN (188464), просто беря 1 секунду.

SELECT * 
FROM 
    (SELECT *, 
      Row_number() OVER(
          ORDER BY datecreated DESC) AS rownum 
    FROM 
    (SELECT DISTINCT c.itemid, 
         (CASE WHEN (Isnull(c.password, '') <> '') THEN 1 ELSE 0 END) AS password, 
         c.title, 
         c.encoderid, 
         c.type, 
         (CASE WHEN c.author = 'education' THEN 'Discovery' ELSE c.type END) AS TYPE, 
         c.publisher, 
         c.description, 
         c.author, 
         c.duration, 
         c.copyright, 
         c.rating, 
         c.userid, 
         Stuff(
           (SELECT DISTINCT ' ' + NAME AS [text()] 
           FROM firsttable SUB 
           LEFT JOIN secondtable AS rgc ON thirdtable = rgc.id 
           WHERE SUB.itemid = c.itemid 
           FOR xml path('')), 1, 1, '')AS [Sub_Categories] 
     FROM fourthtable AS cg 
     LEFT JOIN item AS c ON c.itemid = cg.itemid 
     WHERE Isnull(title, '') <> '' 
     AND c.active = '1' 
     AND c.systemid = '20' 
     AND cg.ownerid IN (294777, 
          228649, 
          188464)) AS a) AS b 
WHERE rownum BETWEEN 1 AND 32 
ORDER BY datecreated DESC 
+0

как вы взяли динамические входы ?? ownerid является varchar ??? Вы разделили их и использовали? или взяли данные из какого-то подзапроса? –

+0

Сначала выполните WHERE плюс ROW_NUMBER (в 'c' и' cg', в CTE или в производной таблице), и после уменьшения количества строк до 32 вы выполняете STUFF. Btw, ваш LEFT JOIN на самом деле является INNER JOIN из-за условия WHERE на 'c' – dnoeth

+0

ownerID получен как список данных varchar из пользовательского интерфейса. – user4130072

ответ

0

С этим мало информации, что невозможно дать какие-либо конкретные идеи, но нормальные общие вещи применяются:

  1. Включите статистики Ио и проверить, что вызывает большую часть логического ввода/вывода и попытаться решить эту
  2. посмотрите на фактический план и проверить, есть ли что-то, что не выглядит хорошо, например:
    • кластерного индекса/сканирование таблицы (новый индекс может решить эту проблему)
    • Основные поиски с огромным количеством строк (добавление больше столбцов индекса может решить эту проблему, либо как обычные или включенные полей)
    • Катушки (новый индекс может решить эту проблему)
    • Большая разница между оценкой и фактическим количеством строк (10x, 100x и так далее)

Чтобы дать какие-либо лучше намеки вы действительно должны включать фактический план, таблицы/индекса структуры по крайней мере, на основных частях и говорят, что слишком много времени (в секундах, минут, часов?)

2

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

SELECT * 
FROM(
    SELECT *, 
    Row_number() OVER(
    ORDER BY datecreated DESC) AS rownum 
    FROM 
    (SELECT DISTINCT c.itemid, 
    (CASE WHEN (Isnull(c.password, '') <> '') THEN 1 ELSE 0 END) AS password, 
    c.title, 
    c.encoderid, 
    c.type, 
    (CASE WHEN c.author = 'education' THEN 'Discovery' ELSE c.type END) AS TYPE, 
    c.publisher, 
    c.description, 
    c.author, 
    c.duration, 
    c.copyright, 
    c.rating, 
    c.userid, 
    Stuff(
     (
      SELECT DISTINCT ' ' + NAME AS [text()] 
      FROM firsttable SUB 
      LEFT JOIN secondtable AS rgc ON thirdtable = rgc.id 
      WHERE SUB.itemid = c.itemid 
      FOR xml path('') 
     ), 1, 1, '' 
    ) AS [Sub_Categories] 
    FROM (
     SELECT cg.itemid 
     FROM fourthtable as cg 
     WHERE cg.ownerid IN (294777,228649, 188464) 
    ) AS cg 
    LEFT JOIN (
     SELECT DISTINCT c.itemid, c.type, c.author, c.title, c.encoderid, c.type, c.publisher, c.description, c.author, c.duration, c.copyright, c.rating,c.userid 
     FROM item as c 
     WHERE Isnull(c.title, '') <> '' 
     AND c.active = '1' 
     AND c.systemid = '20' 
    ) AS c 
     ON c.itemid = cg.itemid 
    ) AS a 
) AS b 
WHERE rownum BETWEEN 1 AND 32 
ORDER BY datecreated DESC 

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

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