sql >> Database >  >> RDS >> Sqlserver

Standaard rijvolgorde in SELECT-query - SQL Server 2008 versus SQL 2012

Je moet teruggaan en ORDER BY . toevoegen clausules in uw code, want zonder deze is de bestelling nooit gegarandeerd. In het verleden had je "geluk" dat je altijd dezelfde bestelling kreeg, maar dat was niet omdat SQL Server 2008 het hoe dan ook garandeerde. Het had hoogstwaarschijnlijk te maken met uw indexen of hoe de gegevens op de schijf werden opgeslagen.

Als u bij de upgrade naar een nieuwe host bent verhuisd, kan het verschil in hardwareconfiguratie alleen al de manier waarop uw query's worden uitgevoerd, hebben veranderd. Om nog maar te zwijgen van het feit dat de nieuwe server statistieken over de tabellen opnieuw zou hebben berekend en de SQL Server 2012 query-optimizer de dingen waarschijnlijk iets anders doet dan die in SQL Server 2008.

Het is een misvatting dat je kunt vertrouwen op de volgorde van een resultaatset in SQL zonder expliciet de volgorde te vermelden waarin je het wilt hebben. SQL-resultaten NOOIT een bestelling hebben waarop u kunt vertrouwen zonder een ORDER BY . te gebruiken clausule. SQL is opgebouwd rond de verzamelingenleer. Zoekresultaten zijn in feite sets (of multi-sets).

Itzik Ben-Gan geeft een goede beschrijving van de verzamelingenleer in relatie tot SQL in zijn boek Microsoft SQL Server 2012 T-SQL Fundamentals

De verzamelingenleer, die zijn oorsprong vindt bij de wiskundige Georg Cantor, is een van de wiskundige takken waarop het relationele model is gebaseerd. Cantor's definitie van een verzameling volgt:

Met een 'verzameling' bedoelen we elke verzameling M tot een geheel van bepaalde, onderscheiden objecten m (die de 'elementen' van M worden genoemd) van onze waarneming of van ons denken. - Joseph W. Dauben en Georg Cantor (Princeton University Press, 1990)

Na een grondige uitleg van de termen in de definitie gaat Itzik verder met te zeggen:

Wat Cantors definitie van een set weglaat, is waarschijnlijk net zo belangrijk als wat het omvat. Merk op dat de definitie geen enkele volgorde vermeldt tussen de set-elementen. De volgorde waarin de set-elementen worden vermeld, is niet belangrijk. De formele notatie voor het weergeven van set-elementen gebruikt accolades:{a, b, c}. Omdat volgorde niet relevant is, kun je dezelfde set uitdrukken als {b, a, c} of {b, c, a}. Vooruitlopend op deze reeks attributen (kolommen genoemd in SQL) die de kop van arelation vormen (een tabel genoemd in SQL), wordt verondersteld dat een element wordt geïdentificeerd door naam - niet door ordinale positie. Beschouw op dezelfde manier de reeks tupels (rijen genoemd door SQL) die de hoofdtekst van de relatie vormen; een element wordt geïdentificeerd door zijn sleutelwaarden - niet door positie. Veel programmeurs hebben moeite om zich aan te passen aan het idee dat er bij het doorzoeken van tabellen geen volgorde is tussen de rijen. Met andere woorden, een query op een tabel kan rijen retourneren in elke volgorde tenzij u uitdrukkelijk verzoekt om de gegevens op een specifieke manier te sorteren, bijvoorbeeld voor presentatiedoeleinden.

Maar ongeacht de academische definitie van een set, heeft zelfs de implementatie in SQL-server nooit enige volgorde in de resultaten gegarandeerd. In deze MSDN-blogpost uit 2005 van een lid van het query-optimalisatieteam staat dat je helemaal niet moet vertrouwen op de volgorde van tussentijdse bewerkingen.

De regels voor het opnieuw ordenen kunnen en zullen deze veronderstelling schenden (en doen dit wanneer het u, de ontwikkelaar, niet uitkomt;). Begrijp alsjeblieft dat wanneer we bewerkingen opnieuw ordenen om een ​​efficiënter plan te vinden, we het bestelgedrag kunnen veranderen voor tussenliggende knooppunten in de boomstructuur. Als je een bewerking in de boomstructuur hebt gezet die uitgaat van een bepaalde tussenliggende volgorde, kan deze breken.

Deze blogpost van Conor Cunningham (Architect, SQL Server Core Engine) "No Seatbelt - Expecting Order without ORDER BY" gaat over SQL Server 2008. Hij heeft een tabel met 20k rijen erin met een enkele index die altijd rijen in dezelfde bestelling. Een ORDER BY toevoegen aan de query verandert niet eens het uitvoeringsplan, dus het is niet alsof het toevoegen van een de query duurder maakt als de optimizer zich realiseert dat hij deze niet nodig heeft. Maar zodra hij nog eens 20k rijen aan de tabel toevoegt, verandert plotseling het queryplan en nu gebruikt het parallellisme en de resultaten zijn niet langer geordend!

Het moeilijkste hier is dat er geen redelijke manier is voor een externe gebruiker om te weten wanneer een plan zal veranderen. De ruimte van alle plannen is enorm en doet je hoofd pijn om na te denken. De optimalisatieprogramma van SQL Server zal plannen wijzigen, zelfs voor eenvoudige zoekopdrachten, als genoeg van de parameters veranderen. Misschien heb je geluk en heb je geen planwijziging, of je kunt gewoon niet aan dit probleem denken en een ORDER BY toevoegen.

Als je meer overtuigingskracht nodig hebt, lees dan deze berichten:

  • Zonder ORDER BY is er geen standaard sorteervolgorde. - Alexander Kuznetsov
  • Orde in de rechtbank! - Thomas Kyte
  • Orde van een resultatenset in SQL - Timothy Wiseman



  1. SQLite JSON_EXTRACT()

  2. Wat is de beste manier om een ​​getallentabel te maken en te vullen?

  3. ROWID (orakel) - enig nut voor?

  4. Hoe sla ik een string langer dan 4000 karakters op in een Oracle Database met Java/JDBC?