powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Перекрестные индексы. Как лучше?
63 сообщений из 63, показаны все 3 страниц
Перекрестные индексы. Как лучше?
    #39715534
Jhonny-2005
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.
Подскажите, есть ли какое-то влияние, если имеются перекрестные индексы.
Пример
1 индекс: a, b, c
2 индекс: b, d
3 индекс b, c, d

Или лучше всего создать индекс, включающий 4 этих поля?
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39715537
Гавриленко Сергей Алексеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лучше для каких запросов?
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39715538
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Jhonny-2005,

Сферические индексы? Для чего лучше? Индексы создают не по традициям и обычаям
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39715545
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Jhonny-2005есть ли какое-то влияние, если имеются перекрестные индексы.Отож... чем больше индексов, тем ниже скорость выполнения запросов, изменяющих данные (INSERT/UPDATE/DELETE).
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39715546
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Jhonny-2005Добрый день.
Подскажите, есть ли какое-то влияние, если имеются перекрестные индексы.
Пример
1 индекс: a, b, c
2 индекс: b, d
3 индекс b, c, d

Или лучше всего создать индекс, включающий 4 этих поля?

Если совсем сферически, то лучше

1. a
2. b
3. c
4. d

есть шансы на index intersection.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39715566
Jhonny-2005
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Гавриленко Сергей АлексеевичЛучше для каких запросов?
Спасибо за аргументированный вопрос.
Хотелось бы понять, лучше для запросов insert/update будет иметь один покрывающий индекс по всем этим полям, или же иметь такой набор индексов без существенной потери скорости на таблице более 10млн записей.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39715569
Гавриленко Сергей Алексеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Jhonny-2005Гавриленко Сергей АлексеевичЛучше для каких запросов?
Спасибо за аргументированный вопрос.
Хотелось бы понять, лучше для запросов insert/update будет иметь один покрывающий индекс по всем этим полям, или же иметь такой набор индексов без существенной потери скорости на таблице более 10млн записей.Для сферических запросов insert лучше будет иметь индексы, которые нпозволят наиболее быстро проверить существующие ограничения (если такоевые есть). Для сферических же запросов update такие, которые позволят быстрее всего найти записи, которые надо изменять. Ну и не забываем еще сферические запросы на select.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39715646
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Jhonny-2005,

вам уже пояснили что количество индексов влияет на скорость изменения данных.

По вашему вопросу:

Если вы делаете такой запрос:
SELECT * FROM table WHERE a = 5
То нужно делать индекс на поле "a"

SELECT a,b,c,d FROM table WHERE a = 5
То нужно делать индекс на поле "a" c включёнными другими полями.

SELECT * FROM table WHERE a = 5 and b = 'x'
То нужно делать индекс по полям "a" и "b" и ставить первое поле индекса то, которое имеет большую селективность (то где больше различных значений).

Там ещё очень много разных вариантов, типа кластерных индексов и т.п.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39715743
Фотография Mind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeSELECT * FROM table WHERE a = 5 and b = 'x'
То нужно делать индекс по полям "a" и "b" и ставить первое поле индекса то, которое имеет большую селективность (то где больше различных значений)Которое чаще используется в других запросах со знаком равенства. А скорость конкретно этого запроса никак не поменяется от того в каком порядке стоят "a" и "b" в индексе.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39715809
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mind,

Я не собираюсь спорить, просто сравните различия в планах одного и того-же запроса, но с разницей в индексах.
Сами можете запустить и проверить.
Заранее спасибо.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
CREATE TABLE testindex (a INT, b CHAR(1))
GO
;WITH xx AS (SELECT * FROM 
	(VALUES (5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A')) AS x(a,b)
) 
INSERT INTO testindex(a,b) SELECT x1.*
FROM xx AS x1,xx AS x2,xx AS x3,xx AS x4,xx AS x5,xx AS x6,xx AS x7;
GO
INSERT INTO testindex(a,b) VALUES (5,'X')
GO
CREATE INDEX IX_testindex ON testindex(a,b)
GO
SELECT * FROM testindex WHERE a = 5 and b = 'X'
GO
DROP INDEX IX_testindex ON testindex;
GO
CREATE INDEX IX_testindex ON testindex(b,a)
GO
SELECT * FROM testindex WHERE a = 5 and b = 'X'
GO
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39715812
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mind,

Хотя, я с вашим замечанием согласен, если в 99% случаев у нас поле "b" в запросах не используется, то скорее всего по нему индекс и не нужен, но это уже нужно смотреть статистику запросов.

В общем-же случае правило такое: Первая колонка в индексе та, у которой наибольшая селективность.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39715831
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeВ общем-же случае правило такое: Первая колонка в индексе та, у которой наибольшая селективность.Видимо и на форуме, и в MS собрались одни идиоты...

https://technet.microsoft.com/en-us/library/jj835095(v=sql.110).aspx?f=255&MSPPError=-2147217396 Consider the order of the columns if the index will contain multiple columns. The column that is used in the WHERE clause in an equal to (=), greater than (>), less than (<), or BETWEEN search condition, or participates in a join, should be placed first. Additional columns should be ordered based on their level of distinctness, that is, from the most distinct to the least distinct.Попробуйте поразмышлять почему рекомендовано именно так.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39715867
Гавриленко Сергей Алексеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeЯ не собираюсь спорить, просто сравните различия в планах одного и того-же запроса, но с разницей в индексах.Вот бы в тестовых планах сравнивать estimate-фигню, ага.
SandalTreeи ставить первое поле индекса то, которое имеет большую селективность (то где больше различных значений).Где-же источник этого бреда, который несут уже который год на собеседованиях?...

UPD. Хотя, некая доля правды в утверждении "ставить первое левее поле в индексе то, которое имеет большую селективность (то где больше различных значений)" есть для случая с запросами вида "... and x > ... and y > ... и т.п.". Но и тут могут быть нюансы.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39715868
Фотография Mind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invm https://technet.microsoft.com/en-us/library/jj835095(v=sql.110).aspx?f=255&MSPPError=-2147217396 Consider the order of the columns if the index will contain multiple columns. The column that is used in the WHERE clause in an equal to (=), greater than (>), less than (<), or BETWEEN search condition, or participates in a join, should be placed first. Additional columns should be ordered based on their level of distinctness, that is, from the most distinct to the least distinct.Попробуйте поразмышлять почему рекомендовано именно так.Если честно я вообще не понимаю что именно они рекомендуют. Какие еще варианты могут быть запихать колонку в WHERE кроме как = > < или BETWEEN? С функциями что-ли? Additional columns это что? Все те что кроме first? Или те что все еще в WHERE но непонятно с какими условиями поиска или те что даже не в WHERE? А зачем они вообще в индексе нужны? А какая тогда разница на их distinctness? И вообще получается что только начиная со второй колонки есть смысл в каком порядке запихивать в индекс, а первую как выбрать если там несколько в WHERE?
Или они хотели сказать "Additionally, columns...". Такое ощущение что эти рекомендации переводили индусы основываясь на доисторических свитках Sybase.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39715869
Фотография Mind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeMind,

Я не собираюсь споритьНе уверен о чем можно вообще спорить с человеком, который не знает в чем разница между статистикой и индексами и что при создании индекса автоматически создается статистика с FULLSCAN, а при автостатистике с успользованием сэмпла. Но при следующем же UPDATE STATISTICS или sp_updatestats все вернется в "норму".

SandalTreeВ общем-же случае правило такое: Первая колонка в индексе та, у которой наибольшая селективность.Есть хоть один аргумент почему надо делать именно так?
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39715870
Фотография Mind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гавриленко Сергей АлексеевичUPD. Хотя, некая доля правды в утверждении "ставить первое левее поле в индексе то, которое имеет большую селективность (то где больше различных значений)" есть для случая с запросами вида "... and x > ... and y > ... и т.п.". Но и тут могут быть нюансы.Ну тут же явно уже другое правило. Все поля в индексе после поля с поиском по диапазону использоваться в запросе как seek predicate не будут и их смело можно пихать в INCLUDE. В таком случае есть смысл из всех полей с поиском на неравенство найти наиболее селективное и поставить его последним , после всех полей с равенством.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39715893
Владимир Затуливетер
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Свои 5 копеек добавлю к сказанному выше.
Покажу на примере, алгоритм выбора индексов.
Тут только селекты, но это также применимо и к апдейтам.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
use tempdb
go

drop table if exists dbo.table1 
go

create table dbo.table1 (
    a int not null
  , b varchar(10) not null
  , c int not null
  , d int not null
)

select a, b
from dbo.table1
where a = 5;
-- лучший индекс: create index IDX1 on dbo.table1 ( a ) include ( b )

select a, b, c, d
from dbo.table1
where a = 5;
-- лучший индекс: create index IDX2 on dbo.table1 ( a ) include ( b, c, d )

select *
from dbo.table1
where a = 5
  and b = 'x';
-- лучший индекс, в зависимости от селективности столбца: 
--   create index IDX3 on dbo.table1 ( a, b ) include ( c, d )
--   create index IDX3 on dbo.table1 ( b, a ) include ( c, d )

select *
from dbo.table1
where a = 5
  and c between 10 and 20
  and b = 'x';
-- лучший индекс, в зависимости от селективности столбца: 
--   create index IDX4 on dbo.table1 ( a, b, c ) include ( d )
--   create index IDX4 on dbo.table1 ( b, a, c ) include ( d )


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

проанализировав все эти запросы и варианты индексов можно сделать один универсальный,
который хорошо покроет все наши запросы
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
create index IDX 
on dbo.table1 ( a, b, c ) 
include ( d )

/*
первой идет "a" т.к. у нас есть запрос который делает выборку только по этому столбцу
второй идет "b", у нас есть запрос с фильтрацией по "а" и "b" столбцам
третий столбец "c", запрос где используются "а" и "b" и "c" с фильтрацией по диапазону

включенный столбец: "d" т.к. почти всегда он в резалтсете
*/


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

ps: фильтрованые индексы я тут не использовал, чтобы не усложнять.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39716211
demind10
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SandalTreeВ общем-же случае правило такое: Первая колонка в индексе та, у которой наибольшая селективность.Есть хоть один аргумент почему надо делать именно так?[/quot]

Может быть дело в статистике ? Если нам все равно какой столбец из участвующих в where или join поставить самым левым, то почему бы не использовать с наибольшей селективностью ? Оптимизатор сможет точнее оценить число строк, которые будут возвращены и поэтому сможет построить более быстрый план ?
Это чисто мое предположение, не претендующее на истину.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39716214
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmSandalTreeВ общем-же случае правило такое: Первая колонка в индексе та, у которой наибольшая селективность.Видимо и на форуме, и в MS собрались одни идиоты...

https://technet.microsoft.com/en-us/library/jj835095(v=sql.110).aspx?f=255&MSPPError=-2147217396 Consider the order of the columns if the index will contain multiple columns. The column that is used in the WHERE clause in an equal to (=), greater than (>), less than (<), or BETWEEN search condition, or participates in a join, should be placed first. Additional columns should be ordered based on their level of distinctness, that is, from the most distinct to the least distinct.Попробуйте поразмышлять почему рекомендовано именно так.
Ну да, я идиот, а ещё и дурак, что пытаюсь высказать своё мнение тут, где все и так умные.
В этом тексте говорится что индексы нужны только для тех колонок, которые используются в WHERE или JOIN.
Однако он не говорит что "нужно создавать отдельные индексы для ВСЕХ полей использующихся в WHERE или JOIN"

Кстати, вы попытались меня обидеть, но так и не сказали в чём-же я не прав.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39716228
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гавриленко Сергей АлексеевичSandalTreeЯ не собираюсь спорить, просто сравните различия в планах одного и того-же запроса, но с разницей в индексах.Вот бы в тестовых планах сравнивать estimate-фигню, ага.
SandalTreeи ставить первое поле индекса то, которое имеет большую селективность (то где больше различных значений).Где-же источник этого бреда, который несут уже который год на собеседованиях?...

UPD. Хотя, некая доля правды в утверждении "ставить первое левее поле в индексе то, которое имеет большую селективность (то где больше различных значений)" есть для случая с запросами вида "... and x > ... and y > ... и т.п.". Но и тут могут быть нюансы.

Вообще-то даже в этом простейшем запросе реальное IO различается на 30%
Если-бы мы взяли пример с джойном нескольких таблиц, то результаты могли-бы быть вообще ужасающие.

Нюансы есть у всех подходов и нельзя религиозно следовать какому-то особому правилу, как например этому.
Всегда нужен балланс скорости и количества качественных индексов.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39716234
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MindSandalTreeMind,

Я не собираюсь споритьНе уверен о чем можно вообще спорить с человеком, который не знает в чем разница между статистикой и индексами и что при создании индекса автоматически создается статистика с FULLSCAN, а при автостатистике с успользованием сэмпла. Но при следующем же UPDATE STATISTICS или sp_updatestats все вернется в "норму" .

SandalTreeВ общем-же случае правило такое: Первая колонка в индексе та, у которой наибольшая селективность.Есть хоть один аргумент почему надо делать именно так?

Там всё горааааздо сложнее со статистиками. Кстати, что по вашему есть " норма "?

По поводу индексов: А какой аргумент вам нужен?
Постройте 2 разных индекса и посмотрите что сервер предпочтёт тот по которуму выше селективность в первой колонке.
Делов-то.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39716236
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mindinvmпропущено...
Попробуйте поразмышлять почему рекомендовано именно так.Если честно я вообще не понимаю что именно они рекомендуют. Какие еще варианты могут быть запихать колонку в WHERE кроме как = > < или BETWEEN? С функциями что-ли? Additional columns это что? Все те что кроме first? Или те что все еще в WHERE но непонятно с какими условиями поиска или те что даже не в WHERE? А зачем они вообще в индексе нужны? А какая тогда разница на их distinctness? И вообще получается что только начиная со второй колонки есть смысл в каком порядке запихивать в индекс, а первую как выбрать если там несколько в WHERE?
Или они хотели сказать "Additionally, columns...". Такое ощущение что эти рекомендации переводили индусы основываясь на доисторических свитках Sybase.
Это ещё что. Там следующий пассаж вообще атас.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39716262
Гавриленко Сергей Алексеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeВообще-то даже в этом простейшем запросе реальное IO различается на 30%Что за дичь вы тут втираете?


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
set nocount on
go
CREATE TABLE testindex (a INT, b CHAR(1))
GO
;WITH xx AS (SELECT * FROM 
	(VALUES (5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A')) AS x(a,b)
) 
INSERT INTO testindex(a,b) SELECT x1.*
FROM xx AS x1,xx AS x2,xx AS x3,xx AS x4,xx AS x5,xx AS x6,xx AS x7;
GO
INSERT INTO testindex(a,b) VALUES (5,'X')
GO
CREATE INDEX IX_testindex_1 ON testindex(a,b)
GO
CREATE INDEX IX_testindex_2 ON testindex(b,a)
go

go
set statistics io on
go
SELECT * FROM testindex with (index = IX_testindex_1 ) WHERE a = 5 and b = 'X'
GO
SELECT * FROM testindex with (index = IX_testindex_2 ) WHERE a = 5 and b = 'X'
GO
set statistics io off
go
--------------------------------------------------------------------------------------------------------------

Table 'testindex'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'testindex'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39716302
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeпытаюсь высказать своё мнениеНе мнение, а утверждение.
SandalTreeВ этом тексте говорится что индексы нужны только для тех колонок, которые используются в WHERE или JOIN.В этом тексте говорится как определять порядок столбцов в индексе. И вашего утверждения в нем нет. Именно для этого он и был процитирован.
SandalTreeОднако он не говорит что "нужно создавать отдельные индексы для ВСЕХ полей использующихся в WHERE или JOIN"А кто говорит, что нужно именно так?
SandalTreeКстати, вы попытались меня обидеть, но так и не сказали в чём-же я не прав.Да? Предложением поразмышлять?

Касаемого вашего тестаБестолку анализировать запросы с уровнем оптимизации TRIVIAL
Поэтому немного изменим данные и запросы
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
/*
Microsoft SQL Server 2017 (RTM-CU9-GDR) (KB4293805) - 14.0.3035.2 (X64)   Jul  6 2018 18:24:36   Copyright (C) 2017 Microsoft Corporation  Developer Edition (64-bit) on Windows 10 Pro 10.0 <X64> (Build 17134: ) (Hypervisor) 
*/

use tempdb;
go

CREATE TABLE testindex (a INT, b varchar(30), dummy char(100))
GO
;WITH xx AS (SELECT * FROM 
	(VALUES (5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A')) AS x(a,b)
) 
INSERT INTO testindex(a,b,dummy) SELECT x1.*, 'a'
FROM xx AS x1,xx AS x2,xx AS x3,xx AS x4,xx AS x5,xx AS x6--,xx AS x7;
GO
INSERT INTO testindex(a,b,dummy) VALUES (5,'X','a')
GO

CREATE INDEX IX_testindex ON testindex(a,b)
GO


1.
Код: sql
1.
2.
3.
4.
5.
6.
set statistics profile on;
go
set statistics io on; SELECT a, b FROM testindex WHERE a = 5 and b = 'X' option (recompile); set statistics io off;
go
set statistics profile off;
go

RowsExecutesStmtTextStmtIdNodeIdParentPhysicalOpLogicalOpArgumentDefinedValuesEstimateRowsEstimateIOEstimateCPUAvgRowSizeTotalSubtreeCostOutputListWarningsTypeParallelEstimateExecutions11SELECT a, b FROM testindex WHERE a = 5 and b = 'X' option (recompile)110NULLNULLNULLNULL500000,5NULLNULLNULL1,604764NULLNULLSELECT0NULL11 |--Index Seek(OBJECT:([tempdb].[dbo].[testindex].[IX_testindex]), SEEK:([tempdb].[dbo].[testindex].[a]=(5) AND [tempdb].[dbo].[testindex].[b]='X') ORDERED FORWARD)121Index SeekIndex SeekOBJECT:([tempdb].[dbo].[testindex].[IX_testindex]), SEEK:([tempdb].[dbo].[testindex].[a]=(5) AND [tempdb].[dbo].[testindex].[b]='X') ORDERED FORWARD[tempdb].[dbo].[testindex].[a], [tempdb].[dbo].[testindex].[b]500000,51,0546060,5501575161,604764[tempdb].[dbo].[testindex].[a], [tempdb].[dbo].[testindex].[b]NULLPLAN_ROW01

Код: plaintext
1.
Table 'testindex'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

2.
Код: sql
1.
2.
3.
4.
5.
6.
set statistics profile on;
go
set statistics io on; SELECT a, b FROM testindex WHERE a = 5 and b = 'X'  option (recompile, querytraceon 9481/*turn on "old" Cardinality Estimator*/); set statistics io off;
go
set statistics profile off;
go

RowsExecutesStmtTextStmtIdNodeIdParentPhysicalOpLogicalOpArgumentDefinedValuesEstimateRowsEstimateIOEstimateCPUAvgRowSizeTotalSubtreeCostOutputListWarningsTypeParallelEstimateExecutions11SELECT a, b FROM testindex WHERE a = 5 and b = 'X' option (recompile, querytraceon 9481/*turn on "old" Cardinality Estimator*/)110NULLNULLNULLNULL1NULLNULLNULL0,0032831NULLNULLSELECT0NULL11 |--Index Seek(OBJECT:([tempdb].[dbo].[testindex].[IX_testindex]), SEEK:([tempdb].[dbo].[testindex].[a]=(5) AND [tempdb].[dbo].[testindex].[b]='X') ORDERED FORWARD)121Index SeekIndex SeekOBJECT:([tempdb].[dbo].[testindex].[IX_testindex]), SEEK:([tempdb].[dbo].[testindex].[a]=(5) AND [tempdb].[dbo].[testindex].[b]='X') ORDERED FORWARD[tempdb].[dbo].[testindex].[a], [tempdb].[dbo].[testindex].[b]10,0031250,0001581160,0032831[tempdb].[dbo].[testindex].[a], [tempdb].[dbo].[testindex].[b]NULLPLAN_ROW01
Код: plaintext
1.
Table 'testindex'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

3.
Код: sql
1.
2.
3.
4.
5.
6.
set statistics profile on;
go
set statistics io on; SELECT a, b, dummy FROM testindex WHERE a = 5 and b = 'X' option (recompile); set statistics io off;
go
set statistics profile off;
go

RowsExecutesStmtTextStmtIdNodeIdParentPhysicalOpLogicalOpArgumentDefinedValuesEstimateRowsEstimateIOEstimateCPUAvgRowSizeTotalSubtreeCostOutputListWarningsTypeParallelEstimateExecutions11SELECT a, b, dummy FROM testindex WHERE a = 5 and b = 'X' option (recompile)110NULLNULLNULLNULL500000,5NULLNULLNULL11,99588NULLNULLSELECT0NULL11 |--Table Scan(OBJECT:([tempdb].[dbo].[testindex]), WHERE:([tempdb].[dbo].[testindex].[a]=(5) AND [tempdb].[dbo].[testindex].[b]='X'))121Table ScanTable ScanOBJECT:([tempdb].[dbo].[testindex]), WHERE:([tempdb].[dbo].[testindex].[a]=(5) AND [tempdb].[dbo].[testindex].[b]='X')[tempdb].[dbo].[testindex].[a], [tempdb].[dbo].[testindex].[b], [tempdb].[dbo].[testindex].[dummy]500000,510,895721,10015811611,99588[tempdb].[dbo].[testindex].[a], [tempdb].[dbo].[testindex].[b], [tempdb].[dbo].[testindex].[dummy]NULLPLAN_ROW01
Код: plaintext
1.
Table 'testindex'. Scan count 1, logical reads 14706, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

4.
Код: sql
1.
2.
3.
4.
5.
6.
set statistics profile on;
go
set statistics io on; SELECT a, b, dummy FROM testindex WHERE a = 5 and b = 'X' option (recompile, querytraceon 9481/*turn on "old" Cardinality Estimator*/); set statistics io off;
go
set statistics profile off;
go

RowsExecutesStmtTextStmtIdNodeIdParentPhysicalOpLogicalOpArgumentDefinedValuesEstimateRowsEstimateIOEstimateCPUAvgRowSizeTotalSubtreeCostOutputListWarningsTypeParallelEstimateExecutions11SELECT a, b, dummy FROM testindex WHERE a = 5 and b = 'X' option (recompile, querytraceon 9481/*turn on "old" Cardinality Estimator*/)110NULLNULLNULLNULL1NULLNULLNULL0,00657038NULLNULLSELECT0NULL11 |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1000]) OPTIMIZED)121Nested LoopsInner JoinOUTER REFERENCES:([Bmk1000]) OPTIMIZEDNULL104,18E-061160,00657038[tempdb].[dbo].[testindex].[a], [tempdb].[dbo].[testindex].[b], [tempdb].[dbo].[testindex].[dummy]NULLPLAN_ROW0100 |--Compute Scalar(DEFINE:([Expr1003]=BmkToPage([Bmk1000])))142Compute ScalarCompute ScalarDEFINE:([Expr1003]=BmkToPage([Bmk1000]))[Expr1003]=BmkToPage([Bmk1000])10,0031250,0001581240,0032831[Bmk1000], [tempdb].[dbo].[testindex].[a], [tempdb].[dbo].[testindex].[b], [Expr1003]NULLPLAN_ROW0111 | |--Index Seek(OBJECT:([tempdb].[dbo].[testindex].[IX_testindex]), SEEK:([tempdb].[dbo].[testindex].[a]=(5) AND [tempdb].[dbo].[testindex].[b]='X') ORDERED FORWARD)154Index SeekIndex SeekOBJECT:([tempdb].[dbo].[testindex].[IX_testindex]), SEEK:([tempdb].[dbo].[testindex].[a]=(5) AND [tempdb].[dbo].[testindex].[b]='X') ORDERED FORWARD[Bmk1000], [tempdb].[dbo].[testindex].[a], [tempdb].[dbo].[testindex].[b]10,0031250,0001581240,0032831[Bmk1000], [tempdb].[dbo].[testindex].[a], [tempdb].[dbo].[testindex].[b]NULLPLAN_ROW0111 |--RID Lookup(OBJECT:([tempdb].[dbo].[testindex]), SEEK:([Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD)172RID LookupRID LookupOBJECT:([tempdb].[dbo].[testindex]), SEEK:([Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD[tempdb].[dbo].[testindex].[dummy]10,0031250,00015811070,0032831[tempdb].[dbo].[testindex].[dummy]NULLPLAN_ROW01
Код: plaintext
1.
Table 'testindex'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39716383
Фотография Mind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeТам всё горааааздо сложнее со статистиками. Кстати, что по вашему есть " норма "?Норма, в данном случае, это значит разницы в планах выполнения между этими двумя индексами не будет никакой, что вприницпе и должно быть.
SandalTreeПо поводу индексов: А какой аргумент вам нужен?
Постройте 2 разных индекса и посмотрите что сервер предпочтёт тот по которуму выше селективность в первой колонке.
Делов-то.Потому что им нужно было хоть какой то индекс выбрать, даже если стоимость одинаковая. С таким же успехом можно брать порядок колонок из Missing Index подсказок, и приводить это как аргумент.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39716438
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гавриленко Сергей Алексеевич,

Вы наверное очень удивитесь, но если ...
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
CREATE INDEX IX_testindex ON testindex(a,b)
GO
set statistics IO ON
go
SELECT * FROM testindex WHERE a = 5 and b = 'X'
GO
set statistics IO off
GO
DROP INDEX IX_testindex ON testindex
GO
CREATE INDEX IX_testindex ON testindex(b,a)
GO
set statistics IO ON
go
SELECT * FROM testindex WHERE a = 5 and b = 'X'
GO
set statistics IO off
GO
DROP INDEX IX_testindex ON testindex
GO
--------------------------------------------------------------------------------------------
Table 'testindex'. Scan count 1, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'testindex'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.


Разница в наших показаниях заключается в том что при использовании индекса №1 сервер использует статистики индекса №2.
В вашем случае для построения статистики по полю "b" был сделан FULLSCAN и значение "Х" попало в статистики.
Получается что-б ваш пример работал, вы должны иметь индексы по ВСЕМ полям, либо делать апдейт статистик с опцией FULLSCAN.

Но даже в вашем случае если вы запустите запрос БЕЗ указания индекса, то сервер выберет индекс №2.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39716439
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mind,

Вообще-то планы разные, так как индекс по полю А "не видит" реального распределения значений по полю "Б" если по полю "Б" нет полной статистики.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39716446
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmКасаемого вашего теста
У меня получился такой-же результат как и у вас, когда я запустил тест в tempdb.

Обнаружилась интересная закономерность.
В tempdb статистика по полю "b" включает значение "X", а в пользовательской базе нет.

В этом и есть разница в IO.
Если надо, могу дать скриншоты статистик, хотя я уже и давал скриншоты разных планов.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39716515
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeОбнаружилась интересная закономерность.
В tempdb статистика по полю "b" включает значение "X", а в пользовательской базе нет.Вы опять фантазируете.
Статистика по (a,b) не может содержать распределение по b, ибо гистограмма хранится только для первого столбца. В любой БД.
Соответственно, статистика по (b,a) будет содержать такое распределение. Опять же в любой БД.
SandalTreeЕсли надо, могу дать скриншоты статистик, хотя я уже и давал скриншоты разных планов.Ваши картинки мало кому интересны в качестве доказательств.
Репро давайте, подтверждающее ваши слова.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39716700
Фотография SIMPLicity_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mindinvmпропущено...
Попробуйте поразмышлять почему рекомендовано именно так.Если честно я вообще не понимаю что именно они рекомендуют. Какие еще варианты могут быть запихать колонку в WHERE кроме как = > < или BETWEEN ? С функциями что-ли? Additional columns это что? Все те что кроме first? Или те что все еще в WHERE но непонятно с какими условиями поиска или те что даже не в WHERE? А зачем они вообще в индексе нужны? А какая тогда разница на их distinctness? И вообще получается что только начиная со второй колонки есть смысл в каком порядке запихивать в индекс, а первую как выбрать если там несколько в WHERE?
Или они хотели сказать "Additionally, columns...". Такое ощущение что эти рекомендации переводили индусы основываясь на доисторических свитках Sybase.
like ?

==================
PS Как вариант like 'АБэЦэ...%' (в идеале должен быть seek вместо scan)....
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39716982
Фотография Mind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeВообще-то планы разные, так как индекс по полю А "не видит"При чем тут индекс "видит", "не видит"? Чушь какую то развели. Оптимизатор решает на основании статистики. Статистики могут быть как привязанные к индексу так и отдельно. И те и другие статистики могут создаваться/обновляться с FULLSCAN и без. Исключение составляет лишь создание/ребилд индекса потому что в этом случае статистика обновляется с FULLSCAN автоматически.
SandalTreeреального распределения значений по полю "Б" если по полю "Б" нет полной статистики. Так при чем тут индекс то, если все дело в статистике? А особенно при чем тут селективность полей?
SandalTreeЕсли надо, могу дать скриншоты статистик, хотя я уже и давал скриншоты разных планов.Все ваши тесты доказывают лишь то что при потере всех конечностей таракан теряет слух. Связи между селективностью и тем какой индекс сервер выбирает никакой, потому что решение оптимизатора в данном случае целиком и полностью зависит от того насколько дерьмовую статистику вы ему подсовываете.
SandalTreeВы наверное очень удивитесь, но если ...Удивляетесь здесь по-моему только вы... Готовы?
Если в ваш пример добавить селективности по полю A
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
DROP TABLE testindex 
GO
CREATE TABLE testindex (a INT, b CHAR(1))
GO
;WITH xx AS (SELECT * FROM 
	(VALUES (5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A')) AS x(a,b)
) 
INSERT INTO testindex(a,b) SELECT x1.*
FROM xx AS x1,xx AS x2,xx AS x3,xx AS x4,xx AS x5,xx AS x6,xx AS x7;
GO
INSERT INTO testindex(a,b) VALUES (1,'A')
INSERT INTO testindex(a,b) VALUES (2,'A')
INSERT INTO testindex(a,b) VALUES (3,'A')
INSERT INTO testindex(a,b) VALUES (4,'A')
INSERT INTO testindex(a,b) VALUES (5,'X')
GO


то сервер все равно продолжит выбирать индекс (b,a)!
SandalTreeПостройте 2 разных индекса и посмотрите что сервер предпочтёт тот по которуму выше селективность в первой колонке. О ужас! Ваша псевдо-теория развалилась.


Можно построить оба индекса одновременно, чтобы исключить безлапых тараканов неполноценную статистику из нашего эксперимента.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
DROP INDEX IX_testindex ON testindex;
CREATE INDEX IX_testindex_1 ON testindex(a,b)
CREATE INDEX IX_testindex_2 ON testindex(b,a)
go
set statistics profile on;
go
SELECT a, b FROM testindex WHERE a = 5 and b = 'X'
go
set statistics profile off;
go

Но сервер упорно продолжает выбирать индекс с меньшей селективностью!
Код: plaintext
1.
|--Index Seek(OBJECT:([TEST].[dbo].[testindex].[ IX_testindex_2 ]), SEEK:([TEST].[dbo].[testindex].[b]='X' AND [TEST].[dbo].[testindex].[a]=(5)) ORDERED FORWARD)
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717250
Фотография SIMPLicity_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MindSandalTreeВообще-то планы разные, так как индекс по полю А "не видит"При чем тут индекс "видит", "не видит"? Чушь какую то развели. Оптимизатор решает на основании статистики. Статистики могут быть как привязанные к индексу так и отдельно. И те и другие статистики могут создаваться/обновляться с FULLSCAN и без. Исключение составляет лишь создание/ребилд индекса потому что в этом случае статистика обновляется с FULLSCAN автоматически.
SandalTreeреального распределения значений по полю "Б" если по полю "Б" нет полной статистики. Так при чем тут индекс то, если все дело в статистике? А особенно при чем тут селективность полей?
SandalTreeЕсли надо, могу дать скриншоты статистик, хотя я уже и давал скриншоты разных планов.Все ваши тесты доказывают лишь то что при потере всех конечностей таракан теряет слух. Связи между селективностью и тем какой индекс сервер выбирает никакой, потому что решение оптимизатора в данном случае целиком и полностью зависит от того насколько дерьмовую статистику вы ему подсовываете.
SandalTreeВы наверное очень удивитесь, но если ...Удивляетесь здесь по-моему только вы... Готовы?
Если в ваш пример добавить селективности по полю A
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
DROP TABLE testindex 
GO
CREATE TABLE testindex (a INT, b CHAR(1))
GO
;WITH xx AS (SELECT * FROM 
	(VALUES (5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A')) AS x(a,b)
) 
INSERT INTO testindex(a,b) SELECT x1.*
FROM xx AS x1,xx AS x2,xx AS x3,xx AS x4,xx AS x5,xx AS x6,xx AS x7;
GO
INSERT INTO testindex(a,b) VALUES (1,'A')
INSERT INTO testindex(a,b) VALUES (2,'A')
INSERT INTO testindex(a,b) VALUES (3,'A')
INSERT INTO testindex(a,b) VALUES (4,'A')
INSERT INTO testindex(a,b) VALUES (5,'X')
GO


то сервер все равно продолжит выбирать индекс (b,a)!
SandalTreeПостройте 2 разных индекса и посмотрите что сервер предпочтёт тот по которуму выше селективность в первой колонке. О ужас! Ваша псевдо-теория развалилась.


Можно построить оба индекса одновременно, чтобы исключить безлапых тараканов неполноценную статистику из нашего эксперимента.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
DROP INDEX IX_testindex ON testindex;
CREATE INDEX IX_testindex_1 ON testindex(a,b)
CREATE INDEX IX_testindex_2 ON testindex(b,a)
go
set statistics profile on;
go
SELECT a, b FROM testindex WHERE a = 5 and b = 'X'
go
set statistics profile off;
go

Но сервер упорно продолжает выбирать индекс с меньшей селективностью!
Код: plaintext
1.
|--Index Seek(OBJECT:([TEST].[dbo].[testindex].[ IX_testindex_2 ]), SEEK:([TEST].[dbo].[testindex].[b]='X' AND [TEST].[dbo].[testindex].[a]=(5)) ORDERED FORWARD)


чуть меняем условие :

set statistics profile on;
go
SELECT a, b FROM testindex WHERE a =5 and b ! = 'X'
go
set statistics profile off;
go

Получаем картину:

StmtText:
Код: sql
1.
  |--Index Seek(OBJECT:([tempdb].[dbo].[testindex].[IX_testindex_1]), SEEK:([tempdb].[dbo].[testindex].[a]=(5) AND [tempdb].[dbo].[testindex].[b] < 'X' OR [tempdb].[dbo].[testindex].[a]=(5) AND [tempdb].[dbo].[testindex].[b] > 'X') ORDERED FORWARD)


при
Argument:
Код: sql
1.
OBJECT:([tempdb].[dbo].[testindex].[IX_testindex_1]), SEEK:([tempdb].[dbo].[testindex].[a]=(5) AND [tempdb].[dbo].[testindex].[b] < 'X' OR [tempdb].[dbo].[testindex].[a]=(5) AND [tempdb].[dbo].[testindex].[b] > 'X') ORDERED FORWARD



Выбор в пользу другого индекса при НЕочевидном (для меня, по крайней мере) преобразовании...
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717252
Фотография SIMPLicity_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PS Вообще, вы куда-то слишком в дебри углубились...
PPS Мне
так кажется....
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717287
Mr. X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SIMPLicity_,

Да какие уж там дебри, все крутится (в основном) вокруг статистики. Из которой тут упоминали только селективность (selectivity), хотя в статистике присутствуют плотность (density), мощьность (cardinality) и гистограмма (histogram). Которые SQL так же использует для оценок.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717365
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmSandalTreeОбнаружилась интересная закономерность.
В tempdb статистика по полю "b" включает значение "X", а в пользовательской базе нет.Вы опять фантазируете.
Статистика по (a,b) не может содержать распределение по b, ибо гистограмма хранится только для первого столбца. В любой БД.
Соответственно, статистика по (b,a) будет содержать такое распределение. Опять же в любой БД.
SandalTreeЕсли надо, могу дать скриншоты статистик, хотя я уже и давал скриншоты разных планов.Ваши картинки мало кому интересны в качестве доказательств.
Репро давайте, подтверждающее ваши слова.

Во первых: есть 2 статистики по обоим полям и когда скуль строит план, то он смотрит на обе. (закрыли этот вопрос?)

Во вторых: при запуске одного и того-же кода в разных базах происходит различная обработка алгоритма выборки сэмла. В одной базе последняя страница входит в сэмпл, а в другой нет, от этого различные статистики и планы. (какого рода репо вам предоставить? Потестируйте в разных базах и посмотрите на сэмплы и статистики.)

В третьих: При двух индексах a-b и b-a скуль почему-то выбирает второй индекс. Сможете ответить на вопрос "почему?"?
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717374
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mindдивляетесь здесь по-моему только вы... Готовы?
Если в ваш пример добавить селективности по полю A
то сервер все равно продолжит выбирать индекс (b,a)!
Да, вы правы. В случае выбора между двумя этими индексами скуль не видит разницы так как планы у них с одинаковой стоимостью.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717616
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeВо первых: есть 2 статистики по обоим полям и когда скуль строит план, то он смотрит на обе. (закрыли этот вопрос?)Еще раз - для уровня оптимизации TRIVIAL статистика не используется для выбора плана. Только для оценки количества строк.
SandalTreeВо вторых: при запуске одного и того-же кода в разных базах происходит различная обработка алгоритма выборки сэмла. В одной базе последняя страница входит в сэмпл, а в другой нет, от этого различные статистики и планы.Да? Вам был даден пример, из которого понятно из-за чего планы разные. Может для вас станет понятнее, когда отключите автосоздание статистики.
Но вы продолжаете фантазировать... Особо порадовала зависимость IO запроса от статистики...
SandalTreeВ третьих: При двух индексах a-b и b-a скуль почему-то выбирает второй индекс. Сможете ответить на вопрос "почему?"?Неужто из-за селективности?
Попробуйте поменять порядок создания индексов.

Ну и напоследок вопрос - каким образом для индексов (a, b) и (b, a), при предикате a = ... and b = ..., селективность столбцов индекса будет влиять на операцию поиска в нем?
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717781
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmSandalTreeВо вторых: при запуске одного и того-же кода в разных базах происходит различная обработка алгоритма выборки сэмла. В одной базе последняя страница входит в сэмпл, а в другой нет, от этого различные статистики и планы.Да? Вам был даден пример, из которого понятно из-за чего планы разные. Может для вас станет понятнее, когда отключите автосоздание статистики.
Вы мне не верите, но сами проверить не желаете. Вот вам скриншот.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717782
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invm,

Разница в IO обусловлена тем что статистики не захватили FULLSAMPLE.
Прочитано только 7% всех записей и значения с последней страницы остались неучтёнными.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
DECLARE @SQL VARCHAR(1000);

SELECT @SQL = 'DBCC SHOW_STATISTICS (''dbo.testindex'',''' + name + ''');' FROM sys.stats as s
INNER JOIN sys.stats_columns AS c
	ON c.object_id = s.object_id AND s.stats_id = c.stats_id
WHERE s.object_id = OBJECT_ID('testindex') AND c.column_id = 1
EXEC (@SQL)
SELECT @SQL = 'DBCC SHOW_STATISTICS (''dbo.testindex'',''' + name + ''');' FROM sys.stats as s
INNER JOIN sys.stats_columns AS c
	ON c.object_id = s.object_id AND s.stats_id = c.stats_id
WHERE s.object_id = OBJECT_ID('testindex') AND c.column_id = 2
EXEC (@SQL)
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717783
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invm,

Как только мы перестроим статистики с полным сканированием то получим результат, который нам продемонстрировал Сергей Гавриленко.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
DECLARE @SQL VARCHAR(1000);
SELECT @SQL = 'UPDATE STATISTICS dbo.testindex ' + name + ' WITH FULLSCAN;' FROM sys.stats as s
INNER JOIN sys.stats_columns AS c
	ON c.object_id = s.object_id AND s.stats_id = c.stats_id
WHERE s.object_id = OBJECT_ID('testindex') AND c.column_id = 1
EXEC (@SQL)
SELECT @SQL = 'UPDATE STATISTICS dbo.testindex ' + name + ' WITH FULLSCAN;' FROM sys.stats as s
INNER JOIN sys.stats_columns AS c
	ON c.object_id = s.object_id AND s.stats_id = c.stats_id
WHERE s.object_id = OBJECT_ID('testindex') AND c.column_id = 2
EXEC (@SQL)
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717785
Гавриленко Сергей Алексеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Откуда появляется четвертое логическое чтение -- не понятно. (Не факт, что оно есть на самом деле и не врет statistics io.) Опять же, если выключить автосоздание статистик на базе, то чтений будет 4 в обоих вариантах, а если индекс прибить руками, то 3 в обоих вариантах.

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

Короче, тут не в структуре индекса дело, а в каких-то сайд-эффектах от статистики.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717787
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeВы мне не верите, но сами проверить не желаете. Вот вам скриншот.Зачем мне ваш скриншот? В моем примере ровно то же самое.
Видимо вы так не удосожились хотя бы его результаты посмотреть.
SandalTreeРазница в IO обусловлена тем что статистики не захватили FULLSAMPLE.
Прочитано только 7% всех записей и значения с последней страницы остались неучтёнными.И каким же образом "неучтенность значений" при компиляции повлияла на статистику IO при выполнении?
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717837
Фотография Mind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гавриленко Сергей АлексеевичОпять же, если выключить автосоздание статистик на базе, то чтений будет 4 в обоих вариантах, а если индекс прибить руками, то 3 в обоих вариантах.А если обновить все статистики с FULLSCAN, то тоже становится 3 чтения вместо 4х.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717839
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тайна 4-й страницы
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
use master;
create database DBTest001;
alter database DBTest001 set auto_create_statistics off;
go

declare @sql nvarchar(max) = N'create event session DBTest001_TrackLatches on server 
add event sqlserver.latch_acquired
(
  action (sqlserver.session_id, sqlserver.sql_text)
  where ([database_id] = {dbid} and session_id = {spid})
)
add target package0.ring_buffer (set max_memory = 1000)
with (event_retention_mode=allow_single_event_loss, max_dispatch_latency = 3 seconds, track_causality=on, startup_state=off);';

if exists(select 1 from sys.server_event_sessions where name = N'DBTest001_TrackLatches')
 drop event session DBTest001_TrackLatches on server;

select
 @sql = replace(replace(@sql, N'{dbid}', cast(db_id('DBTest001') as nvarchar(10))), N'{spid}', cast(@@spid as nvarchar(10)));

exec(@sql);
go

use DBTest001;
go

CREATE TABLE testindex (a INT, b CHAR(1))
GO
;WITH xx AS (SELECT * FROM 
	(VALUES (5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A')) AS x(a,b)
) 
INSERT INTO testindex(a,b) SELECT x1.*
FROM xx AS x1,xx AS x2,xx AS x3,xx AS x4,xx AS x5,xx AS x6,xx AS x7;
GO
INSERT INTO testindex(a,b) VALUES (5,'X')
GO

create statistics ST_testindex__a on testindex (a) --with fullscan;
create statistics ST_testindex__b on testindex (b) --with fullscan;
go

create index IX_testindex on testindex (a, b);
go

create procedure spGetPagesRead
 @UpdateStatisticsMode varchar(10) = null

as
begin
 set nocount on;

 if @UpdateStatisticsMode = 'fullscan'
  begin
   update statistics testindex(ST_testindex__a) with fullscan;
   update statistics testindex(ST_testindex__b) with fullscan;
  end
 else
  begin
   update statistics testindex(ST_testindex__a);
   update statistics testindex(ST_testindex__b);
  end;

 alter event session DBTest001_TrackLatches on server state = start;
 set statistics io on; SELECT a, b FROM testindex WHERE a = 5 and b = 'X'  option (recompile); set statistics io off;

 declare @x xml;

 select
  @x = cast(t.target_data as xml)
 from
  sys.dm_xe_sessions s join
  sys.dm_xe_session_targets t on t.event_session_address = s.address
 where
  s.name = N'DBTest001_TrackLatches';

 alter event session DBTest001_TrackLatches on server state = stop;

 select distinct
  object_name(pa.object_id) as object, pi.file_id, pi.page_id, pa.index_id, pa.page_type_desc
 from
  @x.nodes('/RingBufferTarget/event[@name = "latch_acquired"][data[@name = "mode"][text = "SH"]]') t(n) cross apply
  (select t.n.value('(data[@name = "file_id"]/value)[1]', 'smallint'), t.n.value('(data[@name = "page_id"]/value)[1]', 'int')) pi(file_id, page_id) join
  sys.dm_db_database_page_allocations(db_id(), null, null, null, 'detailed') pa on pa.allocated_page_file_id = pi.file_id and pa.allocated_page_page_id = pi.page_id

end;
go

exec dbo.spGetPagesRead 'fullscan';
exec dbo.spGetPagesRead;
go

drop event session DBTest001_TrackLatches on server;
go

use master;
drop database DBTest001;
go


С fullscan
objectfile_idpage_idindex_idpage_type_descsysobjvalues1431INDEX_PAGEsysobjvalues11281DATA_PAGEsysobjvalues11321DATA_PAGEsyssingleobjrefs1971DATA_PAGEtestindex12904INDEX_PAGEtestindex1380974INDEX_PAGEtestindex1412504INDEX_PAGE

Без fullscan
objectfile_idpage_idindex_idpage_type_desc sysmultiobjrefs 11052INDEX_PAGEsysobjvalues1431INDEX_PAGEsysobjvalues11281DATA_PAGEsysobjvalues11811DATA_PAGEsyssingleobjrefs1971DATA_PAGEtestindex12904INDEX_PAGEtestindex1380974INDEX_PAGEtestindex1412504INDEX_PAGE
Осталось понять какого лешего это попадает в статистику IO.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717859
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В предыдущем примере накосячено.
Исправлено
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
use master;
create database DBTest001;
alter database DBTest001 set auto_create_statistics off;
go

declare @sql nvarchar(max) = N'create event session DBTest001_TrackLatches on server 
add event sqlserver.latch_acquired
(
  action (sqlserver.session_id, sqlserver.sql_text)
  where ([database_id] = {dbid} and session_id = {spid})
)
add target package0.ring_buffer (set max_memory = 1000)
with (event_retention_mode=allow_single_event_loss, max_dispatch_latency = 3 seconds, track_causality=on, startup_state=off);';

if exists(select 1 from sys.server_event_sessions where name = N'DBTest001_TrackLatches')
 drop event session DBTest001_TrackLatches on server;

select
 @sql = replace(replace(@sql, N'{dbid}', cast(db_id('DBTest001') as nvarchar(10))), N'{spid}', cast(@@spid as nvarchar(10)));

exec(@sql);
go

use DBTest001;
go

CREATE TABLE testindex (a INT, b CHAR(1))
GO
;WITH xx AS (SELECT * FROM 
	(VALUES (5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A'),(5,'A')) AS x(a,b)
) 
INSERT INTO testindex(a,b) SELECT x1.*
FROM xx AS x1,xx AS x2,xx AS x3,xx AS x4,xx AS x5,xx AS x6,xx AS x7;
GO
INSERT INTO testindex(a,b) VALUES (5,'X')
GO

create statistics ST_testindex__a on testindex (a) --with fullscan;
create statistics ST_testindex__b on testindex (b) --with fullscan;
go

create index IX_testindex on testindex (a, b);
go

create procedure spGetPagesRead
 @UpdateStatisticsMode varchar(10) = null

as
begin
 set nocount on;

 if @UpdateStatisticsMode = 'fullscan'
  begin
   update statistics testindex(ST_testindex__a) with fullscan;
   update statistics testindex(ST_testindex__b) with fullscan;
  end
 else
  begin
   update statistics testindex(ST_testindex__a);
   update statistics testindex(ST_testindex__b);
  end;

 alter event session DBTest001_TrackLatches on server state = start;
 set statistics io on; SELECT a, b FROM testindex WHERE a = 5 and b = 'X'  option (recompile); set statistics io off;

 declare @x xml;

 select
  @x = cast(t.target_data as xml)
 from
  sys.dm_xe_sessions s join
  sys.dm_xe_session_targets t on t.event_session_address = s.address
 where
  s.name = N'DBTest001_TrackLatches';

 alter event session DBTest001_TrackLatches on server state = stop;

 select
  pi.file_id, pi.page_id, pa.index_id, pa.page_type_desc
 from
  @x.nodes('/RingBufferTarget/event[@name = "latch_acquired"][data[@name = "mode"][text = "SH"]]') t(n) cross apply
  (select t.n.value('(data[@name = "file_id"]/value)[1]', 'smallint'), t.n.value('(data[@name = "page_id"]/value)[1]', 'int')) pi(file_id, page_id) join
  sys.dm_db_database_page_allocations(db_id(), null, null, null, 'detailed') pa on pa.allocated_page_file_id = pi.file_id and pa.allocated_page_page_id = pi.page_id
 where
  pa.object_id = object_id('testindex');

end;
go

exec dbo.spGetPagesRead 'fullscan';
exec dbo.spGetPagesRead;
go

drop event session DBTest001_TrackLatches on server;
go

use master;
drop database DBTest001;
go


С fullscan
file_idpage_idindex_idpage_type_desc12904INDEX_PAGE1380974INDEX_PAGE1412504INDEX_PAGE

Без fullscan
file_idpage_idindex_idpage_type_desc12904INDEX_PAGE1380974INDEX_PAGE1380974INDEX_PAGE1412504INDEX_PAGE
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717863
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invm,

Ну и зачем оно 2 раза читает нижнюю страничку индекса?
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717893
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mind,

Вот нашёл более приближённый пример того что индекс с большей селективностью лучше работает:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
CREATE TABLE dbo.testindex2(ID INT IDENTITY (0,5), i INT, a CHAR(1))
GO
CREATE INDEX ix_testindex1 ON dbo.testindex2(id,i)
GO
CREATE INDEX ix_testindex2 ON dbo.testindex2(i,id)
GO
DECLARE @l INT = 2010;
DECLARE @m INT = @l;
WHILE @m > 0
BEGIN
	INSERT INTO dbo.testindex2(i,a)
	SELECT TOP (@m) @l-@m, 'a' FROM sys.messages
	SET @m -= 5;
END
GO
SET STATISTICS IO ON
GO
SELECT * FROM dbo.testindex2 WITH (INDEX = ix_testindex1)
WHERE i BETWEEN 0 AND 1000 AND id BETWEEN 0 AND 1000
OPTION (RECOMPILE)
GO
SELECT * FROM dbo.testindex2 WITH (INDEX = ix_testindex2)
WHERE i BETWEEN 0 AND 1000 AND id BETWEEN 0 AND 1000
OPTION (RECOMPILE)
GO
SET STATISTICS IO OFF

авторTable 'testindex2'. Scan count 1, logical reads 204, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'testindex2'. Scan count 1, logical reads 1035, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Распределение данных надумано и не реалистично, но это просто пример селективности.
В реальной жизни скорее всего могут быть более серьёзные случаи.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717954
Гавриленко Сергей Алексеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTree,

Ясен пень, что здесь будут разные seek-предикаты, в отличие от запроса с равенством.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39717991
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeНу и зачем оно 2 раза читает нижнюю страничку индекса?Нижнюю? Уверены? :)
А зачем - это вам объяснять. Это же ваша теория "О влиянии неучтенных значений в статистике на количество чтений во время выполнения запроса при идентичных планах выполнения".
SandalTreeВот нашёл более приближённый пример того что индекс с большей селективностью лучше работаетЛед тронулся.
Не хотите переформулировать ваше "общее правило"?
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39718154
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeMind,

Вот нашёл более приближённый пример того что индекс с большей селективностью лучше работает:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
CREATE TABLE dbo.testindex2(ID INT IDENTITY (0,5), i INT, a CHAR(1))
GO
CREATE INDEX ix_testindex1 ON dbo.testindex2(id,i)
GO
CREATE INDEX ix_testindex2 ON dbo.testindex2(i,id)
GO
DECLARE @l INT = 2010;
DECLARE @m INT = @l;
WHILE @m > 0
BEGIN
	INSERT INTO dbo.testindex2(i,a)
	SELECT TOP (@m) @l-@m, 'a' FROM sys.messages
	SET @m -= 5;
END
GO
SET STATISTICS IO ON
GO
SELECT * FROM dbo.testindex2 WITH (INDEX = ix_testindex1)
WHERE i BETWEEN 0 AND 1000 AND id BETWEEN 0 AND 1000
OPTION (RECOMPILE)
GO
SELECT * FROM dbo.testindex2 WITH (INDEX = ix_testindex2)
WHERE i BETWEEN 0 AND 1000 AND id BETWEEN 0 AND 1000
OPTION (RECOMPILE)
GO
SET STATISTICS IO OFF


авторTable 'testindex2'. Scan count 1, logical reads 204, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'testindex2'. Scan count 1, logical reads 1035, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Распределение данных надумано и не реалистично, но это просто пример селективности.
В реальной жизни скорее всего могут быть более серьёзные случаи.


Ваше различие в чтениях вызвано не селективностью индекса, а количеством записей, попадающим в диапазон between по одному и по второму полю


вот вам чуть измененных скрипт, в котором я просто "размазал" значение поля i, домножив его на 100, но не менял селективность ни одного из полей, и получил противоположный вашему результат


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
if object_id('dbo.testindex2')  is not null
	drop table dbo.testindex2

CREATE TABLE dbo.testindex2(ID INT IDENTITY (0,5), i INT, a CHAR(1))
GO
DECLARE @l INT = 2010;
DECLARE @m INT = @l;
WHILE @m > 0
BEGIN
	INSERT INTO dbo.testindex2(i,a)
	SELECT TOP (@m) @l-@m * 100, 'a' FROM sys.messages
	SET @m -= 5;
END
GO
CREATE INDEX ix_testindex1 ON dbo.testindex2(id,i)
GO
CREATE INDEX ix_testindex2 ON dbo.testindex2(i,id)
GO
SET STATISTICS IO ON
GO
SELECT * FROM dbo.testindex2 WITH (INDEX = ix_testindex1)
WHERE i BETWEEN 1 AND 100000 AND id BETWEEN 1 AND 100000
OPTION (RECOMPILE)
GO
SELECT * FROM dbo.testindex2 WITH (INDEX = ix_testindex2)
WHERE i BETWEEN 1 AND 100000 AND id BETWEEN 1 AND 100000
OPTION (RECOMPILE)
GO
SET STATISTICS IO OFF




STATISTICS IOTable 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'testindex2'. Scan count 1, logical reads 58 , physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(0 rows affected)
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'testindex2'. Scan count 1, logical reads 5 , physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39718252
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invmSandalTreeНу и зачем оно 2 раза читает нижнюю страничку индекса?Нижнюю? Уверены? :)
А зачем - это вам объяснять. Это же ваша теория "О влиянии неучтенных значений в статистике на количество чтений во время выполнения запроса при идентичных планах выполнения".
SandalTreeВот нашёл более приближённый пример того что индекс с большей селективностью лучше работаетЛед тронулся.
Не хотите переформулировать ваше "общее правило"?Возможно не так сказал. Не самую нижнюю, а нижнюю "индексную", на которой скуль "не находит" нужного значения.

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

Давайте поставим обратный вопрос: Имеет-ли постановка более селективного поля первым какой-либо негативный эффект?
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39718253
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
msLex,

Спасибо. Это аргумент. Буду думать на более подходящим примером.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39718258
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeВозможно не так сказал. Не самую нижнюю, а нижнюю "индексную", на которой скуль "не находит" нужного значения.А что такое "нижняя индексная"? И "самая нижняя"?
Т.е. на одной и той же странице, первый раз плохо искал и не нашел и для надежности решил поискать еще раз?
Даже если покурить что-нибудь и представить, что это так и есть, то причем тут "неучтенные значения" в статистике?
SandalTreeЕсли делаешь индекс по более чем одному полю и не знаешь как эти поля используются в базе, то самый простой путь это отсортировать по селективностиЕсли не известно как эти поля используются в базе, то делать по ним индекс, мягко говоря, странно.
SandalTreeИмеет-ли постановка более селективного поля первым какой-либо негативный эффект?Т.е. до вас, после двух с лишним страниц обсуждений и примеров, так и не дошло как работает поиск в индексе для предикатов разных типов. Прискорбно.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39718262
Фотография Yasha123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeЕсли делаешь индекс по более чем одному полю и не знаешь как эти поля используются в базе, то самый простой путь это отсортировать по селективности
а чего не в алфавитном порядке?
я вот вообще считаю, если есть поля, начинающиеся с Х,
то их и надо первыми "постановить".
а то еще про селективность надо выяснять, какое селективнее,
а с алфавитом все ясно, а главное,
можно смело переформулировать вопрос след. образом:
Имеет ли постановка поля, начинающегося на буквы Х, первым какой-либо негативный эффект?
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39718441
Фотография Mind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeMind,

Вот нашёл более приближённый пример того что индекс с большей селективностью лучше работаетТо есть вы вообще не понимаете как индексы работают? И то что в вашем запросе для поиска по индексу может использоваться только первое поле? То есть по сути мы сравниваем индекс по id с индексом по i. И тут не надо быть семи пядей во лбу чтобы сказать что индекс по более селективному полю лучше чем по менее селективному. А что там стоит вторым полем вообще особого значения не имеет, с таким же успехом его можно запихать в INCLUDE разницы не будет, все равно сканируется весь диапазон по первому полю.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39718442
Фотография Mind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
msLexВаше различие в чтениях вызвано не селективностью индекса, а количеством записей, попадающим в диапазон between по одному и по второму полюЭто и называется селективность. А пример просто в корне не верен, ибо поиск по диапазону по двум полям не может эффективно использовать оба поля из индекса.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39718444
Фотография Mind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Yasha123SandalTreeЕсли делаешь индекс по более чем одному полю и не знаешь как эти поля используются в базе, то самый простой путь это отсортировать по селективности
а чего не в алфавитном порядке?Да можно еще проще, как это делает missing index подсказыватель, тупо ставить в том же порядке в котором они в таблице идут.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39718449
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Yasha123SandalTreeЕсли делаешь индекс по более чем одному полю и не знаешь как эти поля используются в базе, то самый простой путь это отсортировать по селективности
а чего не в алфавитном порядке?
Может быть просто потому что по теории вероятности селективная колонка будет работать лучше.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39718499
Фотография Mind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandalTreeYasha123пропущено...

а чего не в алфавитном порядке?
Может быть просто потому что по теории вероятности селективная колонка будет работать лучше.Давайте все индексы начинать с ПК таблицы:
Код: sql
1.
2.
CREATE INDEX ix_customer_lastname ON dbo.customer(CustomerId, LastName)
CREATE INDEX ix_customer_city ON dbo.customer(CustomerId, CityId)

Лепота! На первом месте всегда самое селективное поле и главное думать не надо.
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39718502
Фотография SIMPLicity_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MindSandalTreeпропущено...

Может быть просто потому что по теории вероятности селективная колонка будет работать лучше.Давайте все индексы начинать с ПК таблицы:
Код: sql
1.
2.
CREATE INDEX ix_customer_lastname ON dbo.customer(CustomerId, LastName)
CREATE INDEX ix_customer_city ON dbo.customer(CustomerId, CityId)

Лепота! На первом месте всегда самое селективное поле и главное думать не надо.

Это ведь сарказм, да?
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39718556
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MindmsLexВаше различие в чтениях вызвано не селективностью индекса, а количеством записей, попадающим в диапазон between по одному и по второму полюЭто и называется селективность.

Нет

Селективность индекса – это показатель того, сколько строк от общего числа приходится на одно ключевое значение индекса.

И к max-min значению не имеет никакого отношения
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39719080
Фотография Mind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SIMPLicity_Mindпропущено...
Давайте все индексы начинать с ПК таблицы:
Код: sql
1.
2.
CREATE INDEX ix_customer_lastname ON dbo.customer(CustomerId, LastName)
CREATE INDEX ix_customer_city ON dbo.customer(CustomerId, CityId)

Лепота! На первом месте всегда самое селективное поле и главное думать не надо.

Это ведь сарказм, да?
...
Рейтинг: 0 / 0
Перекрестные индексы. Как лучше?
    #39719095
Фотография SandalTree
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SIMPLicity_Mindпропущено...
Давайте все индексы начинать с ПК таблицы:
Код: sql
1.
2.
CREATE INDEX ix_customer_lastname ON dbo.customer(CustomerId, LastName)
CREATE INDEX ix_customer_city ON dbo.customer(CustomerId, CityId)

Лепота! На первом месте всегда самое селективное поле и главное думать не надо.

Это ведь сарказм, да? это скорее издевательство
...
Рейтинг: 0 / 0
63 сообщений из 63, показаны все 3 страниц
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Перекрестные индексы. Как лучше?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]