JavaScript: Wie kann ich eine große Tabelle schneller sortieren?
Hallo zusammen,
ich habe eine große Tabelle in meiner ASP.NET Core Razor Pages Anwendung, die ich clientseitig mit JavaScript sortieren möchte.
Allerdings dauert die Sortierung bei einer großen Datenmenge zu lange, und ich suche nach einer performanten Lösung.
Meine aktuelle Implementierung:
Ich nutze Array.sort() und vergleiche Strings und Zahlen entsprechend, das funktioniert aber das ist nicht effizient genug.
Besonders wenn die Tabelle viele Zeilen (z. B. >10.000) hat, wird die Sortierung langsam.
Meine Anforderungen:
✅ Die Sortierung muss komplett in JavaScript (clientseitig) erfolgen
✅ Sie muss sowohl Texte (Strings mit Umlaute, Sonderzeichen, etc.) als auch Zahlen (inkl. Währungen mit €) schnell sortieren
✅ Die Tabelle wird nachträglich dynamisch mit Daten befüllt (also keine initiale Sortierung im Backend möglich)
✅ Die Lösung soll sehr schnell auch bei großen Datenmengen sein
Ich habe bereits probiert:
❌ Array.sort() (wird langsam bei vielen Zeilen)
❌ localeCompare() (korrekt für Strings, aber langsam)
❌ TypedArrays für Zahlenwerte (bringt nicht genug Speed)
Gibt es eine bessere Möglichkeit, eine HTML-Tabelle performant zu sortieren?
Vielleicht mit Web Worker, einer anderen Datenstruktur oder anderen Algorithmen?
oder gibt es andere Funktionen/Möglichkeiten, die ich noch probieren kann?
hier mein aktueller Ansatz:
Tabelle:
<div class="col-lg-9 col-md-7 col-12">
<div class="table-container">
<table class="table-modern table-hover w-100" id="statistikTable">
<thead>
<tr>
<th onclick="sortTable(0, this)">Datum <img class="sort-icon" src="/img/dgvsort.png" style="display: none;"></th>
<th onclick="sortTable(1, this)">PID <img class="sort-icon" src="/img/dgvsort.png" style="display: none;"></th>
<th onclick="sortTable(2, this)">Nachname <img class="sort-icon" src="/img/dgvsort.png" style="display: none;"></th>
<th onclick="sortTable(3, this)">Vorname <img class="sort-icon" src="/img/dgvsort.png" style="display: none;"></th>
<th onclick="sortTable(4, this)">Rechnungsnetto <img class="sort-icon" src="/img/dgvsort.png" style="display: none;"></th>
<th onclick="sortTable(5, this)">Belegnummer <img class="sort-icon" src="/img/dgvsort.png" style="display: none;"></th>
</tr>
</thead>
<tbody>
@if (Model.StatistikData != null && Model.StatistikData.Rows.Count > 0)
{
foreach (DataRow row in Model.StatistikData.Rows)
{
<tr>
<td>@(((DateTime)row["Datum"]).ToString("dd.MM.yyyy"))</td>
<td>@row["PID"]</td>
<td>@row["KundeNachname"]</td>
<td>@row["KundeVorname"]</td>
<td>@Convert.ToDecimal(row["Rechnungsnetto"]).ToString("N2")</td>
<td>@row["Belegnummer"]</td>
</tr>
}
}
else
{
<tr>
<td colspan="6" class="text-center">Keine Daten gefunden</td>
</tr>
}
</tbody>
</table>
</div>
</div>
meine sort Funktion:
function sortTable(columnIndex, header) {
const table = document.getElementById("statistikTable");
const tbody = table.tBodies[0];
const rows = Array.from(tbody.rows);
const ascending = table.dataset.sortOrder !== "asc";
const isNumericColumn = !isNaN(parseFloat(rows[0].cells[columnIndex].textContent.replace("€", "").replace(",", ".").trim()));
let sortedRows;
if (isNumericColumn) {
sortedRows = rows
.map(row => ({
element: row,
value: parseFloat(row.cells[columnIndex].textContent.replace("€", "").replace(",", ".").trim()) || 0
}))
.sort((a, b) => ascending ? a.value - b.value : b.value - a.value);
} else {
const collator = new Intl.Collator("de", { numeric: true, sensitivity: "base" });
sortedRows = rows
.map(row => ({
element: row,
value: row.cells[columnIndex].textContent.trim()
}))
.sort((a, b) => ascending ? collator.compare(a.value, b.value) : collator.compare(b.value, a.value));
}
const fragment = document.createDocumentFragment();
sortedRows.forEach(({ element }) => fragment.appendChild(element));
tbody.appendChild(fragment);
table.dataset.sortOrder = ascending ? "asc" : "desc";
updateSortIcons(header, ascending);
}
function updateSortIcons(header, ascending) {
document.querySelectorAll(".sort-icon").forEach(icon => {
icon.src = "/img/dgvsort.png";
icon.style.display = "inline";
});
const icon = header.querySelector(".sort-icon");
if (icon) {
icon.src = ascending ? "/img/dgvsortup.png" : "/img/dgvsortdown.png";
icon.style.display = "inline";
}
}
Freue mich über jede Hilfe! 😊