We have several customers that each run a system consisting of 12 databases. Most of these run quite fine but recently two of our "largest" customers are getting a lot of "waiting for non-stale results"-timeouts.
We have done some investigations at the customer with the most problems and found that all the indexes in one of the databases stay stale when the system is just somewhat in use. It
is enough to change just one or a few documents every few minutes to keep the database continuously stale.
This is not acceptable for us or our customers and we need some help in figuring out why our system is behaving so poorly performance-wise.
We did some measurements through RavenStudio on some of the largest indexes in the problematic database during some light usage. We recorded the etag of last modified document and the etags of the three indexes with the largest DocsCount number (SchoolViewIndex, LessonStudentIndex, LessonIndex):
etag of the
last modified SchoolViewIndex LessonStudentIndex LessonIndex
Time document etag etag etag
13:19 11EB0 11A1C 11E64 11E64
13:23 11F06 11E64 11EB0 11EB0
13:24 120A6 11F5C 120A2 120A2
13:24 12374 120A6 12374 12374
13:26 12413 120A6 12374 12374
13:28 128C8 1247A 126A8 126A8
13:30 129F2 126A8 129DF 129DF
13:31 12ED3 12A2A 12A24 12E7A
13:32 12EEE 12A2A 12E7A 12E7A
13:33 12F09 12A2A 12E7A 12E7A
13:36 12F27 12A2A 12E7A 12E7A
13:37 12F5E 12E7A 12F3D 12F3D
During this 18-minute period it was typical to see between one and three LarerStilling documents being modified by users which also triggered a new etag on multiple unmodified Lesson
documents (could be up to several hundreds) because they through their Lesson.Resources[] property referenced them by id.
The strange thing is that the system never achieved non-staleness during this 18-minute period when there were only a few document changes (more than 10, but less than 100) and the total number of etags to spin through was around 5000 (12E7A-11A1C=145Ehex=5214dec), which gives an "etag indexing rate" of just 5 etags per second (5214/18 minutes = 289 per minute = 4.8 per second).
Where can the problem lie?
Also, one of the observations we made was that when resetting an index it triggers a high CPU rate, large disk read and disk write activity in the very beginning, but stabilizes fairly quickly to a much lower CPU and disk read/write activity. Is this normal?
Best regards,
Per Eivind Jenssen,
Developer, Oppad as
=========== System info ==========
Virtual server:
Windows server 2008 R2 Standard, Service Pack 1
CPU Intel Xeon L5...@2.27GHz 2.26GHz
8,00 GB RAM, 64-bit Operating System
RavenDB service
version 2.5.2946
license "Commercial - Subscription"
Database with problem
Total 252.154 documents
Size 24.1GB
28 indexes: 13 are selfmade indexes (some are "from-from"s, some use LoadDocument, some also use Reduce) and 15 "simpler" autoindexes.
=========== The three "largest" indexes ==========
SchoolViewIndex:
AddMap<Lesson>(items => from lesson in items
from resource in lesson.Resources
let schoolPeriodAgg = LoadDocument<SkoleAr>(lesson.SchoolPeriodId)
let grp = LoadDocument<Gruppe>(lesson.Group.GroupId)
let resourceName = resource.ResourceName ?? LoadDocument<INamedAggregate>(resource.ResourceId).Name
let studentName = resource.ResourceType == "Student" ? resource.ResourceName ?? LoadDocument<INamedAggregate>(resource.ResourceId).Name : ""
let potentialStudent = LoadDocument<Elev>(resource.ResourceId)
let studentDeceased = resource.ResourceType == "Student" && ((potentialStudent != null) && potentialStudent.IsDeceased)
where !studentDeceased
select new
{
Acl = new[] {lesson.Id, lesson.Group.GroupId, resource.ResourceId, schoolPeriodAgg.SkoleId}.Concat(grp.ContactTeacherPrincipalIdsAcl),
ContactTeacherPrincipalIdsAcl = new[] { resource.ResourceId }.Concat(grp.ContactTeacherPrincipalIdsAcl),
LessonId = lesson.Id,
LessonId_Reversed = lesson.Id.Reverse(),
StudentId = resource.ResourceType == "Student" ? resource.ResourceId : "",
StudentFullName = studentName,
StudentQuery = resource.ResourceType == "Student" ? new []
{
studentName,
grp.Name
} : new []{""},
GroupId = lesson.Group.GroupId,
GroupId_Reversed = lesson.Group.GroupId.Reverse(),
GroupName = grp.Name,
GroupSubjectCode = grp.FagkodeGruppeNavn,
GradeGroup = grp.KunKarakterer,
lesson.SchoolPeriodId,
SchoolPeriodId_Reversed = lesson.SchoolPeriodId.Reverse(),
resource.ResourceId,
ResourceId_Reversed = resource.ResourceId.Reverse(),
resource.ResourceType,
ResourceName = resourceName,
lesson.StartInterval,
lesson.EndInterval,
});
LessonStudentIndex:
AddMap<Lesson>(items => from lesson in items
let schoolPeriodAgg = LoadDocument<SkoleAr>(lesson.SchoolPeriodId)
from student in lesson.Students
select new
{
Acl = new[] { lesson.Id, lesson.Group.GroupId, student.ResourceId, schoolPeriodAgg != null ? schoolPeriodAgg.SkoleId : "#L#S0#"}
.Union( lesson.Teachers.Select(t=>t.TeacherId)),
LessonId = lesson.Id,
LessonId_Stripped = lesson.Id,
StudentId = student.ResourceId,
StudentId_Stripped = student.ResourceId,
SchoolPeriodId = lesson.SchoolPeriodId,
SchoolPeriodId_Stripped = lesson.SchoolPeriodId,
LessonStatus = student.LessonStatus,
AbsenceType = student.AbsenceType,
LessonRemark = student.Remark,
GroupId = lesson.Group.GroupId,
GroupId_Stripped = lesson.Group.GroupId,
GroupName = lesson.Group.GroupName,
});
LessonIndex:
AddMap<Lesson>(items => from lesson in items
let schoolPeriodAgg = LoadDocument<SkoleAr>(lesson.SchoolPeriodId)
select new
{
Acl = new[] { lesson.Id, lesson.Group.GroupId, schoolPeriodAgg != null ? schoolPeriodAgg.SkoleId : "SP0-SI0" },
lesson.StartInterval,
StartInterval_Date = lesson.StartInterval.Date,
lesson.EndInterval,
HasRegistrations = lesson.Students.Any(s => s.LessonStatus != StudentLessonStatus.NotRegistered) || lesson.Teachers.Any(s => s.LessonStatus !=
TeacherLessonStatus.NotRegistered),
LessonId = lesson.Id,
LessonId_Stripped = lesson.Id,
StudentIds = lesson.Students.Select(s => s.ResourceId),
StudentIds_Stripped = lesson.Students.Select(s => s.ResourceId),
TeacherIds = lesson.Teachers.Select(t => t.ResourceId),
TeacherIds_Stripped = lesson.Teachers.Select(t => t.ResourceId),
SchoolPeriodId = lesson.SchoolPeriodId,
SchoolPeriodId_Stripped = lesson.SchoolPeriodId,
GroupId = lesson.Group.GroupId,
GroupId_Stripped = lesson.Group.GroupId,
GroupName = lesson.Group.GroupName,
});