SQL Server не будет использовать мой индекс

Путем создания метода GetMood virtual в Moody и override в производных классах, должен работать код. Вы уверены, что поместили эти ключевые слова, где они принадлежат? Вот полный код, который компилирует и выполненный очень хорошо:

public class MoodyObject
{
    protected virtual String getMood()
    {
        return "moody";
    }

    public void queryMood()
    {
        Console.WriteLine("I feel " + getMood() + " today!");
    }
}

public class SadObject : MoodyObject
{
    protected override String getMood()
    {
        return "sad";
    }

    //specialization
    public void cry()
    {
        Console.WriteLine("wah...boohoo");
    }
}

public class HappyObject : MoodyObject
{
    protected override String getMood()
    {
        return "happy";
    }

    public void laugh()
    {
        Console.WriteLine("hehehehehehe.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        MoodyObject moodyObject = new MoodyObject();
        SadObject sadObject = new SadObject();
        HappyObject happyObject = new HappyObject();

        Console.WriteLine("How does the moody object feel today?");
        moodyObject.queryMood();
        Console.WriteLine("");
        Console.WriteLine("How does the sad object feel today?");
        sadObject.queryMood();
        sadObject.cry();
        Console.WriteLine("");
        Console.WriteLine("How does the happy object feel today?");
        happyObject.queryMood();
        happyObject.laugh();

        Console.Read();
    }
}

, Возможно, Ваша ошибка прибывает из того, что в Java, все методы являются виртуальными, который не имеет место, C# (как указано Dan C.).

6
задан Ian Elliott 14 July 2009 в 01:57
поделиться

8 ответов

У вас есть 800 тыс. Строк, проиндексированных по столбцам col1, col2, col3. Col2 - это бит, поэтому его селективность 50%. Col3 проверяется в диапазоне (<=), поэтому его селективность также будет примерно на уровне 50%. Что оставляет col1. Запрос составляется для общего параметризованного плана, поэтому он должен учитывать общий случай. Если у вас есть 10 различных значений col1, то ваш индекс вернет приблизительно 800k / 10 * 25%, что составляет около ~ 20k ключей для поиска в кластеризованном индексе для получения части '...'. Если у вас есть 10k различных значений col1, то индекс вернет только 20 ключей для поиска. Как видите, в данном случае важно не то, как вы создаете индекс, а фактические данные. На основе избирательности col1 оптимизатор выберет план на основе сканирования кластерного индекса (лучше, чем поиск ключей 20k, каждый поиск стоит по крайней мере 3-5 чтений страниц) или один на основе некластеризованного индекса (если col1 достаточно селективен). В реальной жизни распределение col1 также играет роль, но это слишком усложнило бы объяснение.

Вы можете воспользоваться преимуществом ретроспективного анализа и заявить, что план неверен, но план является наилучшей оценкой затрат, основанной на по данным, доступным на момент компиляции. Вы можете влиять на него с помощью подсказок (подсказка по индексу, как вы предлагаете, или оптимизация для подсказок, как предлагает Квассной), но тогда ваш запрос может работать лучше для вашего тестового набора и намного хуже для другого набора данных, скажем, для случая, когда @ col1 = <значение, соответствующее 500 тыс. Записей> . Вы также можете сделать индексное покрытие, исключив таким образом "..." в списке проекций, которые требуют поиска по кластеризованному индексу, и в этом случае некластеризованный индекс всегда дает лучшее соответствие стоимости, чем кластерное сканирование.

У Кимберли Трипп есть статья в блоге, посвященная этой теме, она называет ее « переломным моментом », в которой объясняется, почему явно идеальный индекс кандидата игнорируется: некластеризованный индекс не покрывает список проекций и имеет низкую селективность будет рассматриваться как более дорогостоящее, чем кластерное сканирование.

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

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

13
ответ дан 8 December 2019 в 12:22
поделиться

Попробуйте замаскировать свои параметры, чтобы предотвратить анализ параметров:

CREATE PROCEDURE MyProc AS
    @Col1 INT
    -- etc...
AS
    DECLARE @MaskedCol1 INT
    SET @MaskedCol1 = @Col1
    -- etc...

    SELECT
         col1,
         col2…
    FROM
         dbo.My_Table
    WHERE
         col1 = @MaskecCol1 AND
         -- etc...

Звучит глупо, но я видел, как SQL-сервер делал некоторые странные вещи из-за анализа параметров .

1
ответ дан 8 December 2019 в 12:22
поделиться

Вы пытались выбросить бит из индекса?

create index ix1 on My_Table(Col3, Col1) INCLUDE(Col2) 
-- include other columns from the select list if needed

Кроме того, вы исключили остальные столбцы из списка выбора. Вы можете рассмотреть возможность включения их, если их немного, либо в индексе, либо в виде оператора INCLUDE для создания покрывающего индекса для запроса.

1
ответ дан 8 December 2019 в 12:22
поделиться

SQL Server optimizer is not good in optimizing queries that use variables.

If you are sure that you will always benefit from using the index, just put a hint.

If you will put the literal values to the query instead of variables, it will pick the correct statistics and will use the index.

You may also try to put a more light hint:

OPTION (OPTIMIZE FOR (@col1 = 1, @col2 = 0, @col3 = '2009-07-09'))

, which will calculate the best execution plan for these values of the variables, using statistics, and won't stick to using index no matter what.

2
ответ дан 8 December 2019 в 12:22
поделиться

Порядок индекса важен для этого запроса:

CREATE INDEX MyIndex ON MyTable (col3 DESC, col2 ASC, col1 ASC)

Это не столько ASC / DESC, сколько то, что когда sql-сервер соответствует предложению where, он может сначала совпадать с col3 и проходит индекс по этому значению.

1
ответ дан 8 December 2019 в 12:22
поделиться

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

Или вместо этого используется другой индекс?

1
ответ дан 8 December 2019 в 12:22
поделиться

Обнуляемые столбцы? Иногда Sql Server думает, что ему нужно просканировать таблицу, чтобы найти значения NULL.

Попробуйте добавить в запрос «и col1 не равно NULL», это может заставить sqlserver использовать индекс без подсказки.

Также проверьте, есть ли статистика действительно актуальны:

SELECT 
    object_name = Object_Name(ind.object_id),
    IndexName = ind.name,
    StatisticsDate = STATS_DATE(ind.object_id, ind.index_id)
FROM SYS.INDEXES ind
order by STATS_DATE(ind.object_id, ind.index_id) desc
0
ответ дан 8 December 2019 в 12:22
поделиться

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

Если у вас есть столбец TEXT, попробуйте переключить тип данных на VARCHAR (MAX), а затем включить значения в некластеризованный индекс.

0
ответ дан 8 December 2019 в 12:22
поделиться
Другие вопросы по тегам:

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